题目大意:给你一棵树,树的边是一条一条连上去的
在连边的过程中询问某条边的“负载”,即能通过这条边的所有不同的路径的数量
LCT动态维护当前节点的子树大小
size记录该节点的虚子树的大小之和,sum记录该节点为根节点的子树大小
更换虚子节点时,或者连上新的虚子树时,即access和link操作,要注意更新size
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N 100100 5 #define il inline 6 using namespace std; 7 8 int n,m,tp; 9 int stk[N]; 10 struct LinkCutTree{ 11 int fa[N],ch[N][2],rv[N],sz[N],sum[N]; 12 il int idf(int x){return ch[fa[x]][0]==x?0:1;} 13 il void con(int x,int ff,int p){fa[x]=ff,ch[ff][p]=x;} 14 il void rev(int x){swap(ch[x][0],ch[x][1]),rv[x]^=1;} 15 il int isroot(int x){return (ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x)?1:0;} 16 il void pushup(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+sz[x]+1;} 17 il void pushdown(int x) 18 { 19 if(rv[x]){ 20 if(ch[x][0]) rev(ch[x][0]); 21 if(ch[x][1]) rev(ch[x][1]); 22 rv[x]=0; 23 } 24 } 25 il void rot(int x) 26 { 27 int y=fa[x],ff=fa[y],px=idf(x),py=idf(y); 28 if(!isroot(y))ch[ff][py]=x;fa[x]=ff; 29 ch[y][px]=ch[x][px^1],fa[ch[x][px^1]]=y; 30 ch[x][px^1]=y,fa[y]=x; 31 pushup(y),pushup(x); 32 } 33 il void splay(int x) 34 { 35 int y=x;stk[++tp]=x; 36 while(!isroot(y)){stk[++tp]=fa[y],y=fa[y];} 37 while(tp){pushdown(stk[tp--]);} 38 while(!isroot(x)){y=fa[x]; 39 if(isroot(y)) rot(x); 40 else if(idf(y)==idf(x)) rot(y),rot(x); 41 else rot(x),rot(x);} 42 pushup(x); 43 } 44 il void access(int x) 45 { 46 for(int y=0;x!=0;y=x,x=fa[x]) 47 { 48 splay(x); 49 sz[x]-=sum[y]; 50 sz[x]+=sum[ch[x][1]]; 51 ch[x][1]=y,pushup(x); 52 } 53 } 54 il void mkroot(int x){access(x),splay(x),rev(x);} 55 il void split(int x,int y){mkroot(y),access(x),splay(x);} 56 il void link(int x,int y){split(x,y),fa[y]=x,sz[x]+=sum[y],pushup(x);} 57 }lct; 58 int gint() 59 { 60 int rett=0,fh=1;char c=getchar(); 61 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 62 while(c>='0'&&c<='9'){rett=(rett<<3)+(rett<<1)+c-'0';c=getchar();} 63 return rett*fh; 64 } 65 void gchar(char str[]) 66 { 67 int num=0;char c=getchar(); 68 while(c<'A'||c>'Z'){c=getchar();} 69 while(c>='A'&&c<='Z'){str[num++]=c;c=getchar();} 70 str[num]='