1. 程式人生 > >[NOI2015]軟體包管理器

[NOI2015]軟體包管理器

題目描述
Linux使用者和OSX使用者一定對軟體包管理器不會陌生。通過軟體包管理器,你可以通過一行命令安裝某一個軟體包,然後軟體包管理器會幫助你從軟體源下載軟體包,同時自動解決所有的依賴(即下載安裝這個軟體包的安裝所依賴的其它軟體包),完成所有的配置。ebian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是優秀的軟體包管理器。
你決定設計你自己的軟體包管理器。不可避免地,你要解決軟體包之間的依賴問題。如果軟體包A依賴軟體包B,那麼安裝軟體包A以前,必須先安裝軟體包B。同時,如果想要解除安裝軟體包B,則必須解除安裝軟體包A。現在你已經獲得了所有的軟體包之間的依賴關係。而且,由於你之前的工作,除0號軟體包以外,在你的管理器當中的軟體包都會依賴一個且僅一個軟體包,而0號軟體包不依賴任何一個軟體包。依賴關係不存在環(若有m

(m2)個軟體包A1,A2,A3,⋯,Am,其中A1依賴A2A2依賴A3A3依賴A4,……,Am1依賴Am,而Am依賴A1,則稱這m個軟體包的依賴關係構成環),當然也不會有一個軟體包依賴自己。
現在你要為你的軟體包管理器寫一個依賴解決程式。根據反饋,使用者希望在安裝和解除安裝某個軟體包時,快速地知道這個操作實際上會改變多少個軟體包的安裝狀態(即安裝操作會安裝多少個未安裝的軟體包,或解除安裝操作會解除安裝多少個已安裝的軟體包),你的任務就是實現這個部分。注意,安裝一個已安裝的軟體包,或解除安裝一個未安裝的軟體包,都不會改變任何軟體包的安裝狀態,即在此情況下,改變安裝狀態的軟體包數為0。

輸入格式


從檔案manager.in中讀入資料。
輸入檔案的第1行包含1個整數n,表示軟體包的總數。軟體包從0開始編號。
隨後一行包含n1個整數,相鄰整數之間用單個空格隔開,分別表示1,2,3,⋯,n2,n1號軟體包依賴的軟體包的編號。
接下來一行包含1個整數q,表示詢問的總數。之後q行,每行1個詢問。詢問分為兩種:
install x:表示安裝軟體包x
uninstall x:表示解除安裝軟體包x
你需要維護每個軟體包的安裝狀態,一開始所有的軟體包都處於未安裝狀態。
對於每個操作,你需要輸出這步操作會改變多少個軟體包的安裝狀態,隨後應用這個操作(即改變你維護的安裝狀態)。

輸出格式


輸出到檔案manager.out中。
輸出檔案包括q行。
輸出檔案的第i行輸出1個整數,為第i步操作中改變安裝狀態的軟體包數。

輸入樣例#1
7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

輸出樣例#1
3
1
3
2
3

輸入樣例#2
10
0 1 2 1 3 0 0 3 2
10
install 0
install 3
uninstall 2
install 7
install 5
install 9
uninstall 9
install 4
install 1
install 9

輸出樣例#2
1
3
2
1
3
1
1
1
0
1

樣例說明1
樣例說明1
一開始所有的軟體包都處於未安裝狀態。
安裝5號軟體包,需要安裝0,1,5三個軟體包。
之後安裝6號軟體包,只需要安裝6號軟體包。此時安裝了0,1,5,6四個軟體包。
解除安裝1號軟體包需要解除安裝1,5,6三個軟體包。此時只有0號軟體包還處於安裝狀態。
之後安裝4號軟體包,需要安裝1,4兩個軟體包。此時0,1,4處在安裝狀態。最後,解除安裝0號軟體包會解除安裝所有的軟體包。`

資料範圍
資料範圍

思路
裸的樹鏈剖分啊。。。
注意一點:每一棵子樹的dfs序是連續的。

程式碼

#include <cstdio>
#include <algorithm>

const int maxn=100000;

struct sigment_tree
{
    int val[(maxn<<2)+10],lazy[(maxn<<2)+10];

    int updata(int now)
    {
        val[now]=val[now<<1]+val[now<<1|1];
        return 0;
    }

    int pushdown(int now,int left,int right)
    {
        if(lazy[now]!=-1)
        {
            int mid=(left+right)>>1;
            lazy[now<<1]=lazy[now];
            val[now<<1]=(mid-left+1)*lazy[now];
            lazy[now<<1|1]=lazy[now];
            val[now<<1|1]=(right-mid)*lazy[now];
            lazy[now]=-1;
        }
        return 0;
    }

    int build(int now,int left,int right)
    {
        lazy[now]=-1;
        if(left==right)
        {
            val[now]=0;
            return 0;
        }
        int mid=(left+right)>>1;
        build(now<<1,left,mid);
        build(now<<1|1,mid+1,right);
        updata(now);
        return 0;
    }

    int change(int now,int left,int right,int askl,int askr,int changeval)
    {
        if((askl>right)||(askr<left))
        {
            return 0;
        }
        if((askl<=left)&&(right<=askr))
        {
            int res=val[now];
            if(changeval)
            {
                res=(right-left+1)-res;
            }
            lazy[now]=changeval;
            val[now]=(right-left+1)*changeval;
            return res;
        }
        pushdown(now,left,right);
        int mid=(left+right)>>1;
        int res=change(now<<1,left,mid,askl,askr,changeval)+change(now<<1|1,mid+1,right,askl,askr,changeval);
        updata(now);
        return res;
    }
};

int n,m,ans;

struct tree
{
    int pre[maxn+10],now[maxn+10],son[maxn+10],tot;
    int deep[maxn+10],size[maxn+10],fa[maxn+10],wson[maxn+10],dfn[maxn+10],cnt,top[maxn+10];
    sigment_tree st;

    int mem()
    {
        st.build(1,0,n-1);
        return 0;
    }

    int ins(int a,int b)
    {
        tot++;
        pre[tot]=now[a];
        now[a]=tot;
        son[tot]=b;
        fa[b]=a;
        return 0;
    }

    int first_dfs(int u)
    {
        deep[u]=deep[fa[u]]+1;
        size[u]=1;
        int j=now[u];
        while(j)
        {
            int v=son[j];
            first_dfs(v);
            size[u]+=size[v];
            if((!wson[u])||(size[wson[u]]<size[v]))
            {
                wson[u]=v;
            }
            j=pre[j];
        }
        return 0;
    }

    int second_dfs(int u,int topfather)
    {
        top[u]=topfather;
        dfn[u]=cnt;
        cnt++;
        if(wson[u])
        {
            second_dfs(wson[u],topfather);
        }
        int j=now[u];
        while(j)
        {
            int v=son[j];
            if(v!=wson[u])
            {
                second_dfs(v,v);
            }
            j=pre[j];
        }
        return 0;
    }

    int query(int x,int kind)
    {
        if(kind)
        {
            while(top[x]!=0)
            {
                ans+=st.change(1,0,n-1,dfn[top[x]],dfn[x],1);
                x=fa[top[x]];
            }
            ans+=st.change(1,0,n-1,0,dfn[x],1);
        }
        else
        {
            ans+=st.change(1,0,n-1,dfn[x],dfn[x]+size[x]-1,0);
        }
        return 0;
    }
};

tree t;

int main()
{
    scanf("%d",&n);
    t.mem();
    for(int i=1; i<n; i++)
    {
        int a;
        scanf("%d",&a);
        t.ins(a,i);
    }
    t.first_dfs(0);
    t.second_dfs(0,0);
    scanf("%d",&m);
    for(int i=1; i<=m; i++)
    {
        ans=0;
        char opt[10];
        int a;
        scanf("%s%d",opt,&a);
        if(opt[0]=='i')
        {
            t.query(a,1);
        }
        else
        {
            t.query(a,0);
        }
        printf("%d\n",ans);
    }
    return 0;
}