[NOI 2015] Package Manager - Tree Chaining

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, ..., A[m-1] depends on Am, and Am depends on A1, it is said that the dependencies of the m software packages form a ring), of course, no software package depends 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 an uninstalled 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&Output

Input

Line 1 of the input file contains 1 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, and n−1 packages depend on, respectively.

The next line contains an integer q, representing the total number of queries. After q lines, 1 query per line. There are two types of inquiries:

install x: means to install package x

uninstall x: 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#1

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

Output#1

3
1
3
2
3

Input#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

Output#2

1
3
2
1
3
1
1
1
0
1

Solution

Suddenly want to celebrate a wave of 1A purple questions, although it is still far from Shenben
For the obvious tree chain splitting problem, during installation, set 1 on the path from the node to the root, and query the prefix sum at the same time. The answer is the path length minus the prefix sum. When uninstalling, query the sum of subtrees and set all subtrees to 0.
Code::

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype> 
#include<string>

using std::min;
using std::max;
using std::cin;
using std::cout;
using std::endl;
using std::isdigit;
using std::swap;
using std::string;

const int maxn = 100005;

struct edge{
    int to,nxt;
}e[maxn<<1];
struct node{
    int w,tag;
    node()
    {
        w = 0;
        tag = -1;
    }
}tr[maxn<<2];
int lnk[maxn],edgenum;
int dfn[maxn],top[maxn],son[maxn],size[maxn],dep[maxn],f[maxn],cnt;
int n,a,q;

void add(int bgn,int end)
{
    e[++edgenum].to = end;
    e[edgenum].nxt = lnk[bgn];
    lnk[bgn] = edgenum;
}
inline int rd()
{
    int x = 0;
    char c = getchar();
    bool f = false;
    while(!isdigit(c))
    {
        if(c == '-')f = true;
        c = getchar();
    }
    while(isdigit(c))
    {
        x = (x<<1)+(x<<3)+(c^48);
        c = getchar(); 
    }
    return f?-x:x;
}
void pushdown(int cur,int len)
{
    tr[cur<<1].tag = tr[cur].tag;
    tr[cur<<1|1].tag = tr[cur].tag;
    tr[cur<<1].w = tr[cur].tag*(len-(len>>1));
    tr[cur<<1|1].w = tr[cur].tag*(len>>1);
    tr[cur].tag = -1;
}
void pushup(int cur)
{
    tr[cur].w = tr[cur<<1].w + tr[cur<<1|1].w;
}
void dfs(int x,int fa,int d)
{
    size[x] = 1;
    f[x] = fa;
    dep[x] = d;
    for(int p = lnk[x]; p; p = e[p].nxt)
    {
        int y = e[p].to;
        if(y == fa)continue;
        dfs(y,x,d+1);
        size[x] += size[y];
        if(size[y]>size[son[x]]) son[x] = y;
    }
}
void dfs2(int x,int init)
{
    dfn[x] = ++cnt;
    top[x] = init;
    if(!son[x])return;
    dfs2(son[x],init);
    for(int p = lnk[x]; p; p = e[p].nxt)
    {
        int y = e[p].to;
        if(y == f[x]||y == son[x])continue;
        dfs2(y,y); 
    }
}
void set(int cur,int l,int r,int L,int R,int val)
{
    if(L <= l && r <= R)
    {
        tr[cur].tag = val;
        tr[cur].w = val*(r-l+1);
    }
    else
    {
        if(tr[cur].tag != -1)pushdown(cur,r-l+1);
        int mid = (l+r)>>1;
        if(L <= mid)set(cur<<1,l,mid,L,R,val);
        if(R > mid)set(cur<<1|1,mid+1,r,L,R,val);
        pushup(cur);
    }   
}
int query(int cur,int l,int r,int L,int R)
{
    int res = 0;
    if(L <= l && R >= r)
    {
        return tr[cur].w;
    }
    else
    {
        if(tr[cur].tag != -1)pushdown(cur,r-l+1);
        int mid = (l+r)>>1;
        if(L<=mid) res += query(cur<<1,l,mid,L,R);
        if(R>mid) res += query(cur<<1|1,mid+1,r,L,R);
        return res;
    }
    
}
int querys(int x)
{
    return query(1,1,n,dfn[x],dfn[x] + size[x] - 1);
}
int install(int x)
{
    int ret = 0 , path = 0;
    while(x)
    {
        ret += query(1,1,n,dfn[top[x]],dfn[x]);
        set(1,1,n,dfn[top[x]],dfn[x],1);
        path += dfn[x] - dfn[top[x]] + 1;
        x = f[top[x]];
    }
    return path - ret;
}
int uninstall(int x)
{
    int ret = 0;
    ret = querys(x);
    set(1,1,n,dfn[x],dfn[x]+size[x]-1,0);
    return ret;
}

int main()
{
    cin >> n;
    for(int i = 2;i <= n; ++i)
    {
        cin >> a;
        add(a+1,i);
        add(i,a+1);
    }
    dfs(1,0,1);
    dfs2(1,1);
    cin >> q;
    for(int i = 1;i <= q; ++i)
    {
        int x;
        string s;
        cin >> s >> x;
        x += 1;
        if(s[0] == 'i')
            printf("%d\n",install(x));
        else
            printf("%d\n",uninstall(x));
    }
    return 0;
}

Guess you like

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