树剖求调 马蜂清晰
  • 板块学术版
  • 楼主___A__
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/4/8 21:17
  • 上次更新2024/4/8 23:47:50
查看原帖
树剖求调 马蜂清晰
275860
___A__楼主2024/4/8 21:17

P2146

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,f[N],dfn[N],top[N],stamp,h[N],siz[N],depth[N],m,rnk[N];
vector<int>g[N];
struct segtree{
    int l,r,num[2]={},tag=-1,siz;
}t[N*4];
void dfs(int u,int last){
    siz[u]=1,depth[u]=depth[last]+1;
    for(int v:g[u]){
        if(v!=last){
            dfs(v,u),siz[u]+=siz[v];
            if(siz[h[u]]<siz[v]){
                h[u]=v;
            }
        }
    }
}
void dfs(int u,int last,int Top){
    dfn[u]=++stamp,rnk[stamp]=u,top[u]=Top;
    if(h[u]){
        dfs(h[u],u,Top);
    }
    for(int v:g[u]){
        if(v!=last&&v!=h[u]){
            dfs(v,u,v);
        }
    }
}
void pushup(int u){
    t[u].num[0]=t[u*2].num[0]+t[u*2+1].num[0],t[u].num[1]=t[u*2].num[1]+t[u*2+1].num[1];
}
void pushdown(int u){
    if(t[u].tag!=-1){
        t[u*2].tag=t[u].tag,t[u*2+1].tag=t[u].tag,t[u*2].num[t[u].tag]=t[u*2].siz,t[u*2].num[!t[u].tag]=0,t[u*2+1].num[t[u].tag]=t[u*2+1].siz,t[u*2+1].num[!t[u].tag]=0,t[u].tag=-1;
    }
}
int query1(int u,int l,int r,int val){
    if(t[u].l>=l&&t[u].r<=r){
        return t[u].num[val];
    }
    pushdown(u);
    int ret=0,mid=(t[u].l+t[u].r)/2;
    if(l<=mid){
        ret+=query1(u*2,l,r,val);
    }
    if(r>mid){
        ret+=query1(u*2+1,l,r,val);
    }
    return ret;
}
void modify1(int u,int l,int r,int val){
    if(t[u].l>=l&&t[u].r<=r){
        t[u].tag=val,t[u].num[!val]=0,t[u].num[val]=t[u].siz;
        return;
    }
    pushdown(u);
    int mid=(t[u].l+t[u].r)/2;
    if(l<=mid){
        modify1(u*2,l,r,val);
    }
    if(r>mid){
        modify1(u*2+1,l,r,val);
    }
    pushup(u);
}
void build(int u,int l,int r){
    t[u].l=l,t[u].r=r,t[u].siz=r-l+1,t[u].num[0]=t[u].siz;
    if(l==r){
        return;
    }
    int mid=(l+r)/2;
    build(u*2,l,mid),build(u*2+1,mid+1,r);
}
int query2(int u,int v,int val){//u~v val的个数
    u=rnk[u],v=rnk[v];
    int ret=0;
    while(top[u]!=top[v]){
        if(depth[top[u]]<depth[top[v]]){
            swap(u,v);
        }
        ret+=query1(1,dfn[top[u]],dfn[u],val),u=f[top[u]];
    }
    if(depth[u]<depth[v]){
        swap(u,v);
    }
    ret+=query1(1,dfn[v],dfn[u],val);
    return ret;
}
void modify2(int u,int v,int val){//u~v 推平为val
    u=rnk[u],v=rnk[v];
    while(top[u]!=top[v]){
        if(depth[top[u]]<depth[top[v]]){
            swap(u,v);
        }
        modify1(1,dfn[top[u]],dfn[u],val),u=f[top[u]];
    }
    if(depth[u]<depth[v]){
        swap(u,v);
    }
    modify1(1,dfn[v],dfn[u],val);
}
int main(){
    cin>>n;
    for(int i=2;i<=n;i++){
        cin>>f[i],f[i]++,g[f[i]].push_back(i);
    }
    dfs(1,1),dfs(1,1,1),build(1,1,n);
    cin>>m;
    for(string typ;m--;){
        int u;
        cin>>typ>>u,u++;
        if(typ[0]=='i'){//安装 1~i推平为1
            cout<<query2(dfn[1],dfn[u],0)<<'\n';
            modify2(dfn[1],dfn[u],1);
        }
        else{//删除 整个子树推平为0
            cout<<query2(dfn[u],dfn[u]+siz[u]-1,1)<<'\n';
            modify2(dfn[u],dfn[u]+siz[u]-1,0);
        }
    }
}
2024/4/8 21:17
加载中...