题目描述
小强要在NNN个孤立的星球上建立起一套通信系统。这套通信系统就是连接NNN个点的一个树。 这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数量。
例如,在上图中,现在一共有了555条边。其中,(3,8)(3,8)(3,8)这条边的负载是666,因 为有六条简单路径2−3−82-3-82−3−8,2−3−8−72-3-8-72−3−8−7,3−8,3−8−73-8,3-8-73−8,3−8−7,4−3−84-3-84−3−8,4−3−8−74-3-8-74−3−8−7路过了(3,8)(3,8)(3,8)。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的 询问。
输入输出格式
输入格式:
第一行包含两个整数 N,QN, QN,Q,表示星球的数量和操作的数量。星球从 111 开始编号。
接下来的 QQQ 行,每行是如下两种格式之一:
A x y
表示在 xxx和 yyy 之间连一条边。保证之前 xxx 和 yyy是不联通的。Q x y
表示询问 (x,y)(x,y)(x,y) 这条边上的负载。保证 xxx 和 yyy 之间有一条边。
输出格式:
对每个查询操作,输出被查询的边的负载。
输入输出样例
说明
对于所有数据,1≤N,Q≤1051≤N,Q≤10^51≤N,Q≤105
SOLUTION:
lct在维护链的同时维护一个虚子树的信息
CODE:
1 #include<cstdio>
2 #include<cstdlib>
3 #define R register int
4 #define I inline void
5 const int N=100009;
6 int f[N],c[N][2],si[N],s[N];
7 bool r[N];
8 #define lc c[x][0]
9 #define rc c[x][1]
10 inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
11 I pushup(R x){
12 s[x]=s[lc]+s[rc]+si[x]+1;
13 }
14 I pushdown(R x){
15 if(r[x]){
16 R t=lc;lc=rc;rc=t;
17 r[lc]^=1;r[rc]^=1;r[x]=0;
18 }
19 }
20 I pushall(R x){
21 if(nroot(x))pushall(f[x]);
22 pushdown(x);
23 }
24 I rotate(R x){
25 R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
26 if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
27 f[w]=y;f[y]=x;f[x]=z;
28 pushup(y);
29 }
30 I splay(R x){//请忽略这个spaly
31 pushall(x);
32 while(nroot(x))rotate(x);
33 pushup(x);
34 }
35 I access(R x){
36 for(R y=0;x;x=f[y=x]){
37 splay(x);
38 si[x]+=s[rc];
39 si[x]-=s[rc=y];
40 //pushup(x);试着去掉,发现对答案无影响
41 }
42 }
43 I makeroot(R x){
44 access(x);splay(x);
45 r[x]^=1;
46 }
47 I split(R x,R y){
48 makeroot(x);
49 access(y);splay(y);
50 }
51 I link(R x,R y){
52 split(x,y);
53 si[f[x]=y]+=s[x];
54 pushup(y);
55 }//LCT模板到此结束
56 #define G ch=getchar()
57 #define gc G;while(ch<'-')G
58 #define in(z) gc;z=ch&15;G;while(ch>'-')z*=10,z+=ch&15,G;
59 int main(){
60 register char ch;
61 register bool fl;
62 R n,q,u,v;
63 in(n);in(q);
64 for(R i=1;i<=n;++i)s[i]=1;
65 while(q--){
66 gc;fl=ch=='A';in(u);in(v);
67 if(fl)link(u,v);
68 else{
69 makeroot(u); access(v);
70 ///题目保证x和y右边,所以我们把u换位根后,在access
71 /// u和v一定是相邻的
72 printf("%lld
",(long long)(si[u]+1)*(si[v]+1));//可以换成上面提到的另一种
73 }
74 }
75 return 0;
76 }