[NOI2015]软件包管理器

四年前的noi我现在还切不掉我觉得我可以退役了


题目链接:https://www.luogu.org/problem/P2146

题目大意:不想写了

树剖,记下重儿子,然后用线段树维护一下就AC了

#include<bits/stdc++.h>
using namespace std;
const int MAXN=400010;
priority_queue<int> Q;
char c[20];
int T,kk,n,m,head[MAXN],ver[MAXN],nxt[MAXN],tot,fa[MAXN],dep[MAXN],son[MAXN],top[MAXN],pps[MAXN],sz[MAXN],tot2,sum[MAXN],lz[MAXN],x,bf;
void add(int x,int y){
    ver[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}void dfs1(int x){
    dep[x]=dep[fa[x]]+1,sz[x]=1;
    for (int i=head[x];i;i=nxt[i]){
        if (ver[i]==fa[x]) continue;
        fa[ver[i]]=x;dfs1(ver[i]);sz[x]+=sz[ver[i]];
        if (sz[ver[i]]>sz[son[x]]) son[x]=ver[i];
    }
}void dfs2(int x,int fa){
    pps[x]=++tot2,top[x]=fa;
    if (!son[x]) return;
    dfs2(son[x],fa);
    for (int i=head[x];i;i=nxt[i])
        if(!pps[ver[i]]) dfs2(ver[i],ver[i]);
}void upp(int x){sum[x]=sum[x<<1]+sum[x<<1|1];}
void pushdown(int i,int l,int r){
    if (lz[i]==0) return;int mid=l+r>>1;
    if (lz[i]==-1) sum[i<<1]=sum[i<<1|1]=0,lz[i<<1]=lz[i<<1|1]=-1;
    else sum[i<<1]=mid-l+1,sum[i<<1|1]=r-mid,lz[i<<1]=lz[i<<1|1]=1;
    lz[i]=0;return;
}void update(int i,int l,int r,int ql,int qr,int x){
    if (ql<=l&&r<=qr){
        if (!x)lz[i]=-1,sum[i]=0;
        else lz[i]=1,sum[i]=r-l+1;
        return;
    }int mid=l+r>>1;pushdown(i,l,r);
    if (mid>=ql) update(i<<1,l,mid,ql,qr,x);
    if (mid<qr) update(i<<1|1,mid+1,r,ql,qr,x);
    upp(i);
}void change(int v,int x,int y){
    while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,pps[top[x]],pps[x],v);
        x=fa[top[x]];
    }if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,pps[x],pps[y],v);
}int main(){
    scanf("%d",&n);
    for (int i=2;i<=n;i++){
        scanf("%d",&kk);
        add(++kk,i);add(i,kk);
    }scanf("%d",&T);dfs1(1),dfs2(1,1);
    while (T--){
        cin>>c+1;scanf("%d",&kk);bf=sum[1];++kk;
        if (c[1]=='i'){
            change(1,kk,1);
            printf("%d
",abs(sum[1]-bf));
        }else{
            update(1,1,n,pps[kk],pps[kk]+sz[kk]-1,0);
            printf("%d
",abs(sum[1]-bf));
        }
    }return 0;
}
原文地址:https://www.cnblogs.com/XYH-xyh/p/11847328.html