P4219 [BJOI2014]大融合
【题意】
很容易简化,就是求断开路径两点后,两点的子树大小之积
【分析】
这种动态加边,删边的操作就很LCT
这是LCT的一类用法,维护子树信息,为什么要单独把维护子树信息拿出来说呢
因为LCT的特点,认父不认子,所以对于子树的信息维护起来是相对有一定难度的
我们多记录一个信息xsiz表示虚儿子的siz大小,考虑什么操作会影响到它,我们发现在link和access发生了轻边的改变,所以在这些位置要注意维护一下xsiz的信息
还有pushup的时候自然siz更新要加上xsiz的部分
【代码】
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; typedef long long ll; int n,m; struct LCT { int son[2],fa,siz,rev,xsiz; }tr[maxn]; #define ls(x) tr[x].son[0] #define rs(x) tr[x].son[1] #define fa(x) tr[x].fa int q[maxn],len; void clear(int x) { ls(x)=rs(x)=tr[x].siz=tr[x].xsiz=tr[x].rev=tr[x].fa=0; } void pushup(int x) { clear(0); if(x) tr[x].siz=tr[ls(x)].siz+tr[rs(x)].siz+1+tr[x].xsiz; } void pushdown(int x) { if(!tr[x].rev) return; if(ls(x)) swap(ls(ls(x)),rs(ls(x))),tr[ls(x)].rev^=1; if(rs(x)) swap(ls(rs(x)),rs(rs(x))),tr[rs(x)].rev^=1; tr[x].rev=0; } int isroot(int x) { return (ls(fa(x))==x || rs(fa(x))==x); } void rotate(int x) { int f=fa(x),ff=fa(f),d=(x==rs(f)); int w=tr[x].son[d^1]; tr[f].son[d]=w; if(isroot(f)) tr[ff].son[f==rs(ff)]=x; tr[x].son[d^1]=f; fa(w)=f; fa(f)=x; fa(x)=ff; //这几个一定放到最后!!!要不然对isroot有影响!! pushup(f); pushup(x); pushup(ff); } void splay(int x) { q[len=1]=x; for(int y=x;isroot(y);y=fa(y)) q[++len]=fa(y); for(int i=len;i>=1;i--) pushdown(q[i]); while(isroot(x)) { if(isroot(fa(x))) rotate(((x==ls(fa(x))) ^ (fa(x)==ls(fa(fa(x)))))?x:fa(x)); rotate(x); } } void access(int x) { for(int y=0;x;y=x,x=fa(x)) { splay(x); tr[x].xsiz+=tr[rs(x)].siz-tr[y].siz; rs(x)=y; pushup(x); } } void makeroot(int x) { access(x); splay(x); swap(ls(x),rs(x)); tr[x].rev^=1; } void cut(int x,int y) { makeroot(x); access(y); splay(y); ls(y)=fa(x)=0; pushup(x); } void link(int x,int y) { makeroot(x); makeroot(y); fa(x)=y; tr[y].xsiz+=tr[x].siz; } int main() { // freopen("mix.in","r",stdin); //freopen("mix.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { char s[5]; int x,y; scanf("%s",s); scanf("%d%d",&x,&y); if(s[0]=='A') link(x,y); else { cut(x,y); makeroot(x); makeroot(y); ll ans=1LL*tr[x].siz*tr[y].siz; printf("%lld\n",ans); link(x,y); } } return 0; }
rotate认父亲的位置写早了,导致isroot出锅了,调了半天qwq