[Brush title] BZOJ 4196 [Noi2015] Package Manager

Description

Linux users and OSX users must be familiar with package managers. Through the package manager, you can install a certain package with one line of command, and then the package manager will help you download the package from the software source, and automatically resolve all dependencies (that is, download and install the package installation depends on other packages), complete all the configuration. apt-get used by Debian/Ubuntu, yum used by Fedora/CentOS, and homebrew available under OSX are excellent package managers.

You decide to design your own package manager. Inevitably, you have to resolve dependencies between packages. If package A depends on package B, then package B must be installed before installing package A. Meanwhile, if you want to uninstall package B, you must uninstall package A. Now you have all the dependencies between the packages. Also, because of your previous work, all packages in your manager depend on one and only one package except package 0, which does not depend on any package. There is no cycle of dependencies (if there are m(m≥2) packages A1,A2,A3,…,Am, where A1 depends on A2, A2 depends on A3, A3 depends on A4, …, Am−1 depends on Am, and If Am depends on A1, it is said that the dependencies of the m software packages form a ring), of course, no software package will depend on itself.

Now you need to write a dependency resolver for your package manager. According to feedback, users want to quickly know how many packages the operation actually changes when installing and uninstalling a package (i.e. how many non-installed packages will be installed by an install operation, or uninstalled by an uninstall operation? how many installed packages), your task is to implement this part. Note that installing an installed package, or uninstalling a non-installed package, does not change the installation status of any package, i.e. in this case, the number of packages that change the installation status is 0.

Input

Line 1 of the input file contains a positive integer n representing the total number of packages. Packages are numbered from 0.

The next line contains n-1 integers, separated by a single space between adjacent integers, representing the numbers of packages 1, 2, 3, ..., n-2, n-1 packages depend on, respectively.

The next line contains a positive integer q, representing the total number of queries.

After q lines, 1 query per line. There are two types of inquiries:

installx: means to install package x

uninstallx: means to uninstall package x

You need to maintain the installed state of each package, starting with all packages in an uninstalled state. For each operation, you need to output how many packages this operation will change the installation state, and then apply the operation (ie, change the installation state you maintain).

Output

The output file includes q lines.

The i-th line of the output file outputs an integer, which is the number of packages whose installation status was changed in the i-th operation.

Sample Input

7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

Sample Output

3
1
3
2
3

HINT

All packages are initially uninstalled.

To install the No. 5 package, three packages 0, 1, and 5 need to be installed.

After installing the No. 6 package, you only need to install the No. 6 package. Four packages 0,1,5,6 are installed at this time.

Uninstalling the No. 1 package requires uninstalling three packages 1, 5, and 6. Only package 0 is still installed at this time.

After installing the No. 4 package, you need to install two packages 1 and 4. At this time, 0,1,4 are in the installed state.

Finally, uninstalling package 0 will uninstall all packages.

n=100000
q=100000

Solution

Tree sectioning
Consider the line segment tree maintenance sum, the installed single point value is 1, otherwise it is 0,
then when installing, subtract the root to its sum from its dep (because its dep is equivalent to its path to the root). Just how many points)
when uninstalling, you can directly check the neutralization of its subtree.

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100000+10;
int n,m,e,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],fa[MAXN],st[MAXN],ed[MAXN],cnt,dep[MAXN],top[MAXN],hson[MAXN],size[MAXN];
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
#define Mid ((l+r)>>1)
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,l,Mid
#define rson rs,Mid+1,r
struct Segment_Tree{
    int Sum[MAXN<<2],Add[MAXN<<2];
    Segment_Tree(){
        memset(Sum,0,sizeof(Sum));
        memset(Add,-1,sizeof(Add));
    }
    inline void PushUp(int rt)
    {
        Sum[rt]=Sum[ls]+Sum[rs];
    }
    inline void PushDown(int rt,int len)
    {
        Sum[ls]=Add[rt]?(len-(len>>1)):0;
        Sum[rs]=Add[rt]?(len>>1):0;
        Add[ls]=Add[rt];Add[rs]=Add[rt];
        Add[rt]=-1;
    }
    inline void Update(int rt,int l,int r,int L,int R,int k)
    {
        if(L<=l&&r<=R)Sum[rt]=k?(r-l+1):0,Add[rt]=k;
        else
        {
            if(~Add[rt])PushDown(rt,r-l+1);
            if(L<=Mid)Update(lson,L,R,k);
            if(R>Mid)Update(rson,L,R,k);
            PushUp(rt);
        }
    }
    inline int Query(int rt,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)return Sum[rt];
        else
        {
            if(~Add[rt])PushDown(rt,r-l+1);
            int res=0;
            if(L<=Mid)res+=Query(lson,L,R);
            if(R>Mid)res+=Query(rson,L,R);
            return res;
        }
    }
};
Segment_Tree T;
#undef Mid
#undef ls
#undef rs
#undef lson
#undef rson
inline void insert(int x,int y)
{
    to[++e]=y;
    nex[e]=beg[x];
    beg[x]=e;
}
inline void dfs1(int x,int f)
{
    int res=0;
    fa[x]=f;dep[x]=dep[f]+1;size[x]=1;
    for(register int i=beg[x];i;i=nex[i])
        if(to[i]==f)continue;
        else
        {
            dfs1(to[i],x);
            size[x]+=size[to[i]];
            if(size[to[i]]>res)res=size[to[i]],hson[x]=to[i];
        }
}
inline void dfs2(int x,int tp)
{
    st[x]=++cnt;top[x]=tp;
    if(hson[x])dfs2(hson[x],tp);
    for(register int i=beg[x];i;i=nex[i])
        if(to[i]==fa[x]||to[i]==hson[x])continue;
        else dfs2(to[i],to[i]);
    ed[x]=cnt;
}
inline void init()
{
    dfs1(1,0);
    dfs2(1,1);
}
inline int Getans(int x)
{
    int res=0;
    while(x)
    {
        res+=T.Query(1,1,n,st[top[x]],st[x]);
        x=fa[top[x]];
    }
    return res;
}
inline void Doans(int x,int k)
{
    while(x)
    {
        T.Update(1,1,n,st[top[x]],st[x],k);
        x=fa[top[x]];
    }
}
int main()
{
    read(n);
    for(register int i=2;i<=n;++i)
    {
        int x;read(x);x++;
        insert(i,x);insert(x,i);
    }
    init();
    read(m);
    while(m--)
    {
        char opt[10];int x;
        scanf("%s",opt);read(x);x++;
        if(opt[0]=='i')
        {
            write(dep[x]-Getans(x),'\n');
            Doans(x,1);
        }
        if(opt[0]=='u')
        {
            write(T.Query(1,1,n,st[x],ed[x]),'\n');
            T.Update(1,1,n,st[x],ed[x],0);
        }
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324648983&siteId=291194637