BZOJ 4855 [Jsoi2016]轻重路径
题解:用树链剖分来维护树链剖分
令d[x]=size[heavyson[x]]-size[lightson[x]]
当d[x]<0时轻重儿子关系改变
用数据结构维护d[x]并找到这些位置改变即可
时间复杂度O(不会分析)
#include<iostream> #include<cstdio> #include<cstring> #define lo now<<1 #define ro now<<1|1 using namespace std; const int maxn=200009; int n,m; long long nowans=0; int havein[maxn],root=0; int del[maxn]; int ls[maxn],rs[maxn]; int father[maxn],siz[maxn],dep[maxn]; int idp[maxn],top[maxn],ref[maxn],hson[maxn]; void Dfs1(int now,int fa){ father[now]=fa; dep[now]=dep[fa]+1; siz[now]=1; if(ls[now]){ Dfs1(ls[now],now); siz[now]+=siz[ls[now]]; if(siz[ls[now]]>siz[hson[now]])hson[now]=ls[now]; } if(rs[now]){ Dfs1(rs[now],now); siz[now]+=siz[rs[now]]; if(siz[rs[now]]>siz[hson[now]])hson[now]=rs[now]; } } int dfsclock=0; void Dfs2(int now,int toppoint){ if(now==toppoint)nowans-=now; idp[now]=++dfsclock; ref[dfsclock]=now; top[now]=toppoint; if(!hson[now])return; Dfs2(hson[now],toppoint); if((ls[now])&&(ls[now]!=hson[now]))Dfs2(ls[now],ls[now]); if((rs[now])&&(rs[now]!=hson[now]))Dfs2(rs[now],rs[now]); } struct SegmentTree{ int l,r; int tag,mn;//siz[heavy[now]]-siz[light[son]] int havetop;//father[top[now]] }tree[maxn<<2]; inline void pushup(int now){ tree[now].mn=min(tree[lo].mn,tree[ro].mn); tree[now].havetop=(tree[lo].havetop|tree[ro].havetop); } inline void pushdown(int now){ if(tree[now].tag){ tree[lo].tag+=tree[now].tag; tree[ro].tag+=tree[now].tag; tree[lo].mn+=tree[now].tag; tree[ro].mn+=tree[now].tag; tree[now].tag=0; } } void BuildTree(int now,int l,int r){ tree[now].l=l;tree[now].r=r; tree[now].tag=0; if(l==r){ int x=ref[l]; tree[now].mn=siz[hson[x]]-min(siz[ls[x]],siz[rs[x]]); tree[now].havetop=0; return; } int mid=(l+r)>>1; BuildTree(lo,l,mid); BuildTree(ro,mid+1,r); pushup(now); } void Updatasec(int now,int ll,int rr,int x){ if(tree[now].l>=ll&&tree[now].r<=rr){ tree[now].tag+=x; tree[now].mn+=x; return; } int mid=(tree[now].l+tree[now].r)>>1; pushdown(now); if(ll<=mid)Updatasec(lo,ll,rr,x); if(rr>mid)Updatasec(ro,ll,rr,x); pushup(now); } void Updatatop(int now,int ll,int rr,int x){ if(ll>rr)return; if(tree[now].r<ll)return; if(tree[now].l>rr)return; if(tree[now].l==tree[now].r){ tree[now].mn+=x; return; } pushdown(now); if(tree[lo].havetop)Updatatop(lo,ll,rr,x); if(tree[ro].havetop)Updatatop(ro,ll,rr,x); pushup(now); } void Changetop(int now,int ll,int rr){ if(ll>rr)return; if(tree[now].r<ll)return; if(tree[now].l>rr)return; if(tree[now].l==tree[now].r){ tree[now].mn=-tree[now].mn; tree[now].havetop=1; int x=ref[tree[now].l]; if(ls[x]==hson[x]){ nowans=nowans-ls[x]+rs[x]; hson[x]=rs[x]; }else{ nowans=nowans-rs[x]+ls[x]; hson[x]=ls[x]; } return; } pushdown(now); if(tree[lo].mn<0)Changetop(lo,ll,rr); if(tree[ro].mn<0)Changetop(ro,ll,rr); pushup(now); } void Updatapoint(int now,int p,int x){ if(tree[now].l==tree[now].r){ tree[now].mn+=x; if(tree[now].mn<0){ tree[now].mn=-tree[now].mn; tree[now].havetop=0; int o=ref[p]; if(ls[o]==hson[o]){ nowans=nowans-ls[o]+rs[o]; hson[o]=rs[o]; }else{ nowans=nowans-rs[o]+ls[o]; hson[o]=ls[o]; } } return; } int mid=(tree[now].l+tree[now].r)>>1; pushdown(now); if(p<=mid)Updatapoint(lo,p,x); else Updatapoint(ro,p,x); pushup(now); } void ChangePath(int u){ int x=u; while(x){ int tx=top[x]; Updatasec(1,idp[tx],idp[x],-1); Updatatop(1,idp[tx],idp[x]-1,2); Changetop(1,idp[tx],idp[x]-1); // x=tx;int fa=father[x]; // if(!fa)break; // if(hson[fa]!=x){ // Updatapoint(1,idp[fa],2); // }else{ // Updatapoint(1,idp[fa],0); // } x=father[tx];tx=top[x]; } x=u; while(x){ x=top[x]; int fa=father[x]; if(!fa)break; if(hson[fa]!=x){ Updatapoint(1,idp[fa],2); }else{ Updatapoint(1,idp[fa],0); } x=fa; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&ls[i],&rs[i]); havein[ls[i]]++; havein[rs[i]]++; } for(int i=1;i<=n;++i)nowans+=i; for(int i=1;i<=n;++i)if(!havein[i])root=i; Dfs1(root,0); Dfs2(root,root); BuildTree(1,1,n); scanf("%d",&m); printf("%lld\n",nowans); del[0]=1; while(m--){ int x;scanf("%d",&x); del[x]=1; ChangePath(x); if(ls[father[x]]==x){ if(del[rs[father[x]]])nowans-=x; }else{ if(del[ls[father[x]]])nowans-=x; } printf("%lld\n",nowans); } return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!