bzoj4196: [Noi2015]软件包管理器

树链剖分。

这道题就写个dfs序,乱搞一下就过了。

简单型的树剖

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200000 + 10;
const int maxm = 400000 + 10;
int g[maxn],v[maxm],next[maxm],eid;
int size[maxn],son[maxn],top[maxn],f[maxn];
int st[maxn],ed[maxn],vid;
int n,m,x;
char op[20];

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;
}

struct Segtree {
    #define lc(x) ((x)<<1)
    #define rc(x) (((x)<<1)|1)
    
    int sumv[maxm],sam[maxm];
    int l[maxm],r[maxm];
    
    void update(int x) {
        sumv[x]=sumv[lc(x)]+sumv[rc(x)];
    }
    
    void push(int x) {
        if(sam[x]==-1) return;
        sam[lc(x)]=sam[x];
        sumv[lc(x)]=sam[x]*(r[lc(x)]-l[lc(x)]+1);
        sam[rc(x)]=sam[x];
        sumv[rc(x)]=sam[x]*(r[rc(x)]-l[rc(x)]+1);
        sam[x]=-1;
    }
    
    void change(int x,int L,int R,int val) {
        if(R<l[x] || L>r[x]) return;
        if(L<=l[x] && r[x]<=R) {
            sam[x]=val; 
            sumv[x]=(r[x]-l[x]+1)*val; 
            return;
        }
        push(x);
        change(lc(x),L,R,val);
        change(rc(x),L,R,val);    
        update(x);
    }
    
    int query(int x,int L,int R) {
        if(R<l[x] || L>r[x]) return 0;
        if(L<=l[x] && r[x]<=R) return sumv[x];
        push(x);
        return (query(lc(x),L,R)+query(rc(x),L,R));
    }
    
    
    void build(int x,int L,int R) {
        l[x]=L; r[x]=R; sam[x]=-1;
        if(L==R) return;
        int mid=(L+R)>>1;
        build(lc(x),L,mid);
        build(rc(x),mid+1,R);
    }
    
}seg;


void dfs1(int u) {
    size[u]=1;
    for(int i=g[u];~i;i=next[i]) {
        dfs1(v[i]);
        size[u]+=size[v[i]];
        if(size[v[i]]>size[son[u]]) son[u]=v[i];
    }
}

void dfs2(int u,int r) {
    top[u]=r; st[u]=++vid;
    if(son[u]) dfs2(son[u],r);
    for(int i=g[u];~i;i=next[i]) if(v[i] != son[u]) 
        dfs2(v[i],v[i]); 
    ed[u]=vid;
}

void solve(int x) {
    int res=0;
    while(x) {
        res+=(st[x]-st[top[x]]+1)-seg.query(1,st[top[x]],st[x]);
        seg.change(1,st[top[x]],st[x],1);
        x=top[x];
        x=f[x];
    }
    printf("%d\n",res);
}


int main() {
    memset(g,-1,sizeof(g));
    scanf("%d",&n);
    for(int i=2;i<=n;i++) {
        scanf("%d",&f[i]);
        f[i]++;
        addedge(f[i],i);
    }
    seg.build(1,1,n);
    dfs1(1); dfs2(1,1);
    scanf("%d",&m);
    while(m--) {
        scanf("%s%d",op,&x);
        x++;
        if(op[0]=='i') solve(x);
        else {
            printf("%d\n",seg.query(1,st[x],ed[x]));
            seg.change(1,st[x],ed[x],0);
        }
    }
    return 0;    
}
posted @ 2016-06-30 18:13  invoid  阅读(392)  评论(0编辑  收藏  举报