BZOJ4530 [BJOI2014]大融合(LCT)
题目描述
小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。 这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数量。
例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因 为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。 现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的 询问。
输入格式
第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。
接下来的Q行,每行是如下两种格式之一:
A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。
Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。 1≤N,Q≤100000
输出格式
对每个查询操作,输出被查询的边的负载。
样例一
input
8 6 A 2 3 A 3 4 A 3 8 A 8 7 A 6 5 Q 3 8
output
6
解题思路:
维护子树信息,建虚树嘛。
pushup时将虚子树答案合并即可。
然后在换儿子/父亲时更新虚子树信息。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lll tr[spc].ch[0] 5 #define rrr tr[spc].ch[1] 6 #define ls ch[0] 7 #define rs ch[1] 8 const int N=200000; 9 struct trnt{ 10 int ch[2]; 11 int fa; 12 int lzt; 13 int wgt; 14 int wgti; 15 bool anc; 16 }tr[N]; 17 int n,q; 18 char cmd[10]; 19 bool whc(int spc) 20 { 21 return tr[tr[spc].fa].rs==spc; 22 } 23 void pushup(int spc) 24 { 25 tr[spc].wgt=tr[spc].wgti+1+tr[lll].wgt+tr[rrr].wgt; 26 return ; 27 } 28 void trr(int spc) 29 { 30 if(!spc) 31 return ; 32 tr[spc].lzt^=1; 33 std::swap(lll,rrr); 34 return ; 35 } 36 void pushdown(int spc) 37 { 38 if(tr[spc].lzt) 39 { 40 trr(lll); 41 trr(rrr); 42 tr[spc].lzt=0; 43 } 44 return ; 45 } 46 void recal(int spc) 47 { 48 if(!tr[spc].anc) 49 recal(tr[spc].fa); 50 pushdown(spc); 51 return ; 52 } 53 void rotate(int spc) 54 { 55 int f=tr[spc].fa; 56 bool k=whc(spc); 57 tr[f].ch[k]=tr[spc].ch[!k]; 58 tr[spc].ch[!k]=f; 59 if(tr[f].anc) 60 { 61 tr[f].anc=0; 62 tr[spc].anc=1; 63 }else 64 tr[tr[f].fa].ch[whc(f)]=spc; 65 tr[spc].fa=tr[f].fa; 66 tr[f].fa=spc; 67 tr[tr[f].ch[k]].fa=f; 68 pushup(f); 69 pushup(spc); 70 return ; 71 } 72 void splay(int spc) 73 { 74 recal(spc); 75 while(!tr[spc].anc) 76 { 77 int f=tr[spc].fa; 78 if(tr[f].anc) 79 { 80 rotate(spc); 81 return ; 82 } 83 if(whc(spc)^whc(f)) 84 rotate(spc); 85 else 86 rotate(f); 87 rotate(spc); 88 } 89 return ; 90 } 91 void access(int spc) 92 { 93 int lst=0; 94 while(spc) 95 { 96 splay(spc); 97 tr[spc].wgti-=tr[lst].wgt; 98 tr[spc].wgti+=tr[rrr].wgt; 99 tr[rrr].anc=true; 100 tr[lst].anc=false; 101 rrr=lst; 102 pushup(spc); 103 lst=spc; 104 spc=tr[spc].fa; 105 } 106 return ; 107 } 108 void Mtr(int spc) 109 { 110 access(spc); 111 splay(spc); 112 trr(spc); 113 return ; 114 } 115 void split(int x,int y) 116 { 117 Mtr(x); 118 access(y); 119 splay(y); 120 return ; 121 } 122 void link(int x,int y) 123 { 124 split(x,y); 125 tr[x].fa=y; 126 tr[y].wgti+=tr[x].wgt; 127 pushup(y); 128 return ; 129 } 130 int main() 131 { 132 scanf("%d%d",&n,&q); 133 for(int i=1;i<=n;i++) 134 tr[i].anc=true; 135 while(q--) 136 { 137 scanf("%s",cmd); 138 if(cmd[0]=='A') 139 { 140 int x,y; 141 scanf("%d%d",&x,&y); 142 link(x,y); 143 }else{ 144 int x,y; 145 scanf("%d%d",&x,&y); 146 split(x,y); 147 long long ans=(long long)((long long)(tr[x].wgti+1)*(long long)(tr[y].wgti+1)); 148 printf("%lld\n",ans); 149 } 150 } 151 return 0; 152 }