1. 程式人生 > >Luogu4219 BJOI2014 大融合 LCT

Luogu4219 BJOI2014 大融合 LCT

傳送門

題意:寫一個數據結構,支援圖上連邊(保證圖是森林)和詢問一條邊兩端的連通塊大小的乘積。$\text{點數、詢問數} \leq 10^5$


圖上連邊,$LCT$跑不掉

支援子樹$size$有點麻煩。我們需要虛子樹的$size$和(實子樹的可以直接$pushup$),那麼我們對於每一個點就去維護其虛子樹的$size$和,那麼每一個點的子樹和就是可以維護的了。可以知道只有$link$和$access$操作會修改虛子樹和(其他都在實鏈上進行操作),稍微加一點東西就行了。相對來說還是比較裸。

注意$pushup$的改變。

  1 #include<bits/stdc++.h>
  2
//This code is written by Itst 3 using namespace std; 4 5 inline int read(){ 6 int a = 0; 7 bool f = 0; 8 char c = getchar(); 9 while(c != EOF && !isdigit(c)){ 10 if(c == '-') 11 f = 1; 12 c = getchar(); 13 } 14 while(c != EOF && isdigit(c)){
15 a = (a << 3) + (a << 1) + (c ^ '0'); 16 c = getchar(); 17 } 18 return f ? -a : a; 19 } 20 21 const int MAXN = 100010; 22 struct node{ 23 int size , ch[2] , fa , allSize; 24 bool mark; 25 }Tree[MAXN]; 26 int N , M; 27 28 inline bool nroot(int x){
29 return Tree[Tree[x].fa].ch[0] == x || Tree[Tree[x].fa].ch[1] == x; 30 } 31 32 inline bool son(int x){ 33 return Tree[Tree[x].fa].ch[1] == x; 34 } 35 36 inline void pushup(int x){ 37 Tree[x].allSize = Tree[Tree[x].ch[0]].allSize + Tree[Tree[x].ch[1]].allSize + Tree[x].size + 1; 38 } 39 40 inline void ZigZag(int x){ 41 bool f = son(x); 42 int y = Tree[x].fa , z = Tree[y].fa , w = Tree[x].ch[f ^ 1]; 43 if(nroot(y)) 44 Tree[z].ch[son(y)] = x; 45 Tree[x].fa = z; 46 Tree[x].ch[f ^ 1] = y; 47 Tree[y].fa = x; 48 Tree[y].ch[f] = w; 49 if(w) 50 Tree[w].fa = y; 51 pushup(y); 52 pushup(x); 53 } 54 55 inline void pushdown(int x){ 56 if(Tree[x].mark){ 57 Tree[Tree[x].ch[0]].mark ^= 1; 58 Tree[Tree[x].ch[1]].mark ^= 1; 59 Tree[x].mark = 0; 60 swap(Tree[x].ch[0] , Tree[x].ch[1]); 61 } 62 } 63 64 void pushdown_all(int x){ 65 if(nroot(x)) 66 pushdown_all(Tree[x].fa); 67 pushdown(x); 68 } 69 70 inline void Splay(int x){ 71 pushdown_all(x); 72 while(nroot(x)){ 73 if(nroot(Tree[x].fa)) 74 ZigZag(son(x) == son(Tree[x].fa) ? Tree[x].fa : x); 75 ZigZag(x); 76 } 77 } 78 79 inline void access(int x){ 80 for(int y = 0 ; x ; y = x , x = Tree[x].fa){ 81 Splay(x); 82 Tree[x].size = Tree[x].size + Tree[Tree[x].ch[1]].allSize - Tree[y].allSize; 83 Tree[x].ch[1] = y; 84 pushup(x); 85 } 86 } 87 88 inline void makeroot(int x){ 89 access(x); 90 Splay(x); 91 Tree[x].mark ^= 1; 92 } 93 94 inline void split(int x , int y){ 95 makeroot(x); 96 access(y); 97 Splay(y); 98 } 99 100 inline void link(int x , int y){ 101 split(x , y); 102 Tree[x].fa = y; 103 Tree[y].size += Tree[x].allSize; 104 pushup(y); 105 } 106 107 inline char getc(){ 108 char c = getchar(); 109 while(!isupper(c)) 110 c = getchar(); 111 return c; 112 } 113 114 int main(){ 115 #ifndef ONLINE_JUDGE 116 freopen("4219.in" , "r" , stdin); 117 //freopen("4219.out" , "w" , stdout); 118 #endif 119 N = read(); 120 for(int i = 1 ; i <= N ; ++i) 121 Tree[i].allSize = 1; 122 for(M = read() ; M ; --M) 123 if(getc() == 'A') 124 link(read() , read()); 125 else{ 126 int a = read() , b = read(); 127 split(a , b); 128 printf("%lld\n" , 1ll * Tree[a].allSize * (Tree[b].allSize - Tree[a].allSize)); 129 } 130 return 0; 131 }