链接:https://loj.ac/problem/2230
思路:
设立siz数组保存虚点信息,sum表示总信息
维护子树信息link操作和access操作需要进行一些改动
可参考博客:https://www.cnblogs.com/GXZlegend/p/7061458.html
实现代码;
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define ls c[x][0] #define rs c[x][1] const int M = 4e5+10; const int inf = 1e9; int top; int sum[M],c[M][2],val[M],fa[M],rev[M],mn[M],S[M]; int siz[M]; inline void up(int x){ sum[x] = sum[ls] + sum[rs] + siz[x] + 1; } inline void pushrev(int x){ swap(ls,rs); rev[x] ^= 1; } inline bool isroot(int x){ return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; } inline void rotate(int x){ int y = fa[x],z = fa[y]; int k = c[y][1] == x; if(!isroot(y)) c[z][c[z][1]==y]=x; fa[x] = z; c[y][k] = c[x][k^1]; fa[c[x][k^1]] = y; c[x][k^1] = y; fa[y] = x; up(y); up(x); } inline void pushdown(int x){ if(rev[x]){ if(ls) pushrev(ls); if(rs) pushrev(rs); rev[x] = 0; } } inline void splay(int x){ S[top=1]=x; for(int i = x;!isroot(i);i=fa[i]) S[++top] = fa[i]; while(top) pushdown(S[top--]); while(!isroot(x)){ int y = fa[x],z = fa[y]; if(!isroot(y)) (c[y][1]==x)^(c[z][1]==y)?rotate(x):rotate(y); rotate(x); } } inline void access(int x){ //维护子树 for(int y = 0;x;y = x,x = fa[x]) splay(x),siz[x] += sum[rs] - sum[y],c[x][1] = y,up(x); //for(int y = 0;x;y = x,x = fa[x]) //splay(x),c[x][1] = y,up(x); } inline void makeroot(int x){ access(x); splay(x); pushrev(x); } inline void split(int x,int y){ makeroot(x); access(y); splay(y); } inline void link(int x,int y){ //维护子树 makeroot(x); makeroot(y); fa[x] = y; siz[y]+=sum[x]; up(y); // makeroot(x);fa[x] = y; } inline void cut(int x,int y){ split(x,y); fa[x] = c[y][0] = 0; up(y); } inline int findroot(int x){ access(x); splay(x); while(ls) x = ls; return x; } int main() { int n,q,u,v; scanf("%d%d",&n,&q); char op[10]; while(q--){ scanf("%s",op); scanf("%d%d",&u,&v); if(op[0] == 'A') link(u,v); else { split(u,v); printf("%lld ",1LL*sum[u]*(sum[v]-sum[u])); } } }