【Luogu】P4219大融合(LCT)
LCTrotate打错尬死
容易发现本题就是问两边子树大小乘积,于是开个数组动态维护LCT每个节点虚子树上有多少点,在Access和Link的时候更新即可。
#include<cstdio> #include<cstdlib> #include<cctype> #include<algorithm> #include<cstring> #include<map> #define maxn 400020 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int size[maxn]; int stack[maxn],top; struct Splay{ struct Node{ int e[2],fa,sum,tag,val; }tree[maxn]; inline int iden(int x){ return x==tree[tree[x].fa].e[1]; } inline bool isroot(int x){ return x!=tree[tree[x].fa].e[0]&&x!=tree[tree[x].fa].e[1]; } inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; } inline void reverse(int x){ swap(tree[x].e[0],tree[x].e[1]); tree[x].tag^=1; } inline void update(int x){ tree[x].sum=tree[tree[x].e[0]].sum+tree[tree[x].e[1]].sum+size[x]+1; } inline void pushdown(int x){ if(tree[x].tag==0) return; if(tree[x].e[0]) reverse(tree[x].e[0]); if(tree[x].e[1]) reverse(tree[x].e[1]); tree[x].tag=0; } void rotate(int x){ int y=tree[x].fa; int r=tree[y].fa; int sony=iden(x),sonr=iden(y); tree[x].fa=r; if(!isroot(y)) tree[r].e[sonr]=x; int b=tree[x].e[sony^1]; connect(b,y,sony); connect(y,x,sony^1); update(y); } void pushto(int x){ top=0; while(!isroot(x)){ stack[++top]=x; x=tree[x].fa; } pushdown(x); while(top) pushdown(stack[top--]); } void splay(int x){ pushto(x); while(!isroot(x)){ int fa=tree[x].fa; if(!isroot(fa)){ if(iden(fa)==iden(x)) rotate(fa); else rotate(x); } rotate(x); } update(x); } void access(int x){ int last=0; while(x){ splay(x); size[x]+=tree[tree[x].e[1]].sum; size[x]-=tree[last].sum; tree[x].e[1]=last; update(x); last=x; x=tree[x].fa; } return; } void makeroot(int x){ access(x); splay(x); reverse(x); } inline int findroot(int x){ access(x); splay(x); while(tree[x].e[0]) x=tree[x].e[0]; return x; } inline void split(int x,int y){ makeroot(x); access(y); splay(y); } inline void link(int x,int y){ split(x,y); size[y]+=tree[x].sum; tree[x].fa=y; update(y); } }s; int cnt; int main(){ int n=read(),m=read(); for(int i=1;i<=n;++i) s.tree[i].sum=1; for(int i=1;i<=m;++i){ char c[10]; scanf("%s",c); int from=read(),to=read(); if(c[0]=='A') s.link(from,to); else{ s.split(from,to); printf("%lld\n",(long long)(size[from]+1)*(size[to]+1)); } } return 0; }