LOJ 2130 软件包管理器

熟练剖分

路径到根直接向上跳

#include <iostream>
#include <cassert>
#include <string>

using namespace std;

const int MAXN=101111;

int N, M;
int P;
string com;

struct Vert{
    int Fa, Son, Bro;
    int Size, Dep;
    int MainSon, Top;
    int Dps, Dpr;
} V[MAXN];

void DFS1(int at){
    V[at].Size=1;
    for(int to=V[at].Son;to>0;to=V[to].Bro){
        V[to].Dep=V[at].Dep+1;
        DFS1(to);
        V[at].Size+=V[to].Size;
        if(V[at].MainSon<=0 || V[to].Size>V[V[at].MainSon].Size)    V[at].MainSon=to;
    }
}

int Dfn[MAXN], DFN;

void DFS2(int at, int t){
    ++DFN;
    Dfn[DFN]=at;V[at].Dps=DFN;
    V[at].Top=t;
    if(V[at].MainSon>0) DFS2(V[at].MainSon, t);
    for(int to=V[at].Son;to>0;to=V[to].Bro){
        if(to==V[at].MainSon)   continue;
        DFS2(to, to);
    }
    V[at].Dpr=DFN;/**/
}

struct Node{
    int l, r;
    int Sum;
    int opt;
} T[MAXN<<2];

int L, R, op;
int Sum;

void BuildTree(int l, int r, int at){
    T[at].l=l;T[at].r=r;T[at].Sum=0;T[at].opt=-1;
    if(l<r){
        int m=(l+r)>>1;
        BuildTree(l, m, at<<1);
        BuildTree(m+1, r, (at<<1)|1);
    }
}

void opr(int at){
    T[at].Sum=op*(T[at].r-T[at].l+1);
}

void cop(int at){
    T[at].opt=op;
}

void pdw(int at){
    if(T[at].opt==-1)   return;
    int top=op;op=T[at].opt;
    opr(at<<1);cop(at<<1);
    opr((at<<1)|1);cop((at<<1)|1);
    op=top;T[at].opt=-1;
}

void pup(int at){
    T[at].Sum=T[at<<1].Sum+T[(at<<1)|1].Sum;
}

int Ask(int at){
    if(T[at].l>=L && T[at].r<=R){
        return T[at].Sum;
    }
    pdw(at);
    int m=(T[at].l+T[at].r)>>1;
    int ret=0;
    if(L<=m)    ret+=Ask(at<<1);
    if(R>m) ret+=Ask((at<<1)|1);
    return ret;
}

void Update(int at){
    if(T[at].l>=L && T[at].r<=R){
        T[at].Sum=op*(T[at].r-T[at].l+1);
        T[at].opt=op;
        return;
    }
    pdw(at);
    int m=(T[at].l+T[at].r)>>1;
    if(L<=m)    Update(at<<1);
    if(R>m) Update((at<<1)|1);
    pup(at);
}

int main(){
    ios_base::sync_with_stdio(false);
    
    cin >> N;
    for(int i=2, f;i<=N;++i){
        cin >> f;++f;
        V[i].Fa=f;V[i].Bro=V[f].Son;V[f].Son=i;
    }
    
    V[1].Dep=1;
    DFS1(1);
    DFS2(1, 1);
    
    assert(DFN==N);
    BuildTree(1, N, 1);
    
    cin >> M;
    while(M--){
        cin >> com >> P;++P;
        Sum=0;
        if(com[0]=='i'){
            op=1;
            for(int k=P;k>0;k=V[V[k].Top].Fa){
                L=V[V[k].Top].Dps;R=V[k].Dps;
                Sum+=Ask(1);
                Update(1);
            }
            cout << V[P].Dep-Sum << endl;
        }
        else{
            op=0;
            L=V[P].Dps;R=V[P].Dpr;
            Sum=Ask(1);
            Update(1);
            cout << Sum << endl;
        }
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Pickupwin/p/9094146.html