bzoj 4530[BJOI2014]大融合 - LCT维护虚树大小

BZOJ4530 [Bjoi2014]大融合

Time Limit: 30 Sec  Memory Limit: 512 MB

Description

小强要在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)。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的
询问。

Input

第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。
接下来的Q行,每行是如下两种格式之一:
A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。
Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。
1≤N,Q≤100000

Output

对每个查询操作,输出被查询的边的负载。

Sample Input

8 6
A 2 3
A 3 4
A 3 8
A 8 7
A 6 5
Q 3 8

Sample Output

6

 

这道题是一道用LCT维护虚树大小的板子题

我们只需要单独用一个变量存储虚树大小,当一个节点的一条重链变成轻链时,它的虚树大小就加上断开的子树大小即可,反之减掉即可

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define LL long long
  6 #define lc t[x].ch[0]
  7 #define rc t[x].ch[1] 
  8 
  9 using namespace std;
 10 
 11 const int MAXN = 1e5 + 10;
 12 
 13 int N, Q;
 14 char opr[10];
 15 
 16 int s[MAXN];
 17 struct node {
 18     int ch[2];
 19     int fa;
 20     int lazy;
 21     int size;
 22     int val; 
 23 } t[MAXN];
 24 
 25 inline LL read()
 26 {
 27     LL x = 0, w = 1; char ch = 0;
 28     while(ch < '0' || ch > '9') {
 29         if(ch == '-') {
 30             w = -1;
 31         }
 32         ch = getchar();
 33     }
 34     while(ch >= '0' && ch <= '9') {
 35         x = x * 10 + ch - '0';
 36         ch = getchar();
 37     }
 38     return x * w;
 39 }
 40 
 41 void pushdown(int x)
 42 {
 43     if(t[x].lazy) {
 44         swap(lc, rc);
 45         t[lc].lazy ^= 1;
 46         t[rc].lazy ^= 1;
 47         t[x].lazy = 0;
 48     }
 49 }
 50 
 51 bool isroot(int x)
 52 {
 53     return t[t[x].fa].ch[0] != x && t[t[x].fa].ch[1] != x;
 54 }
 55 
 56 void pushup(int x)
 57 {
 58     t[x].val = t[x].size + t[lc].val + t[rc].val + 1;
 59 }
 60 
 61 void rotate(int x)
 62 {
 63     int y = t[x].fa, z = t[y].fa;
 64     int l, r;
 65     if(!isroot(y)) {
 66         if(t[z].ch[0] == y) {
 67             t[z].ch[0] = x;
 68         } else {
 69             t[z].ch[1] = x;
 70         }
 71     }
 72     if(t[y].ch[0] == x) {
 73         l = 0;
 74     } else {
 75         l = 1;
 76     }
 77     r = l ^ 1;
 78     t[y].ch[l] = t[x].ch[r], t[t[x].ch[r]].fa = y;
 79     t[x].ch[r] = y, t[x].fa = z, t[y].fa = x;
 80     pushup(y);
 81     pushup(x);
 82 }
 83 
 84 void splay(int x)
 85 {
 86     int y = x;
 87     int cnt = 0;
 88     while(!isroot(y)) {
 89         s[++cnt] = y;
 90         y = t[y].fa;
 91     }
 92     s[++cnt] = y;
 93     while(cnt) {
 94         pushdown(s[cnt--]);
 95     }
 96     while(!isroot(x)) {
 97         int y = t[x].fa, z = t[y].fa;
 98         if(!isroot(y)) {
 99             if((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) {
100                 rotate(x);
101             } else {
102                 rotate(y);
103             }
104         }
105         rotate(x);
106     }
107 }
108 
109 void access(int x)
110 {
111     for(int y = 0; x; y = x, x = t[x].fa) {
112         splay(x);
113         t[x].size += t[rc].val;
114         rc = y;
115         t[x].size -= t[rc].val;
116         pushup(x);
117     }
118 }
119 
120 void makeroot(int x)                                                                 
121 {
122     access(x);
123     splay(x);
124     t[x].lazy ^= 1;
125 }
126 
127 void split(int x, int y)
128 {
129     makeroot(x);
130     access(y);
131     splay(y);
132 }
133 
134 void link(int x, int y)
135 {
136     makeroot(x);
137     //split(x, y);
138     t[x].fa = y;
139     t[y].size += t[x].val;
140     pushup(y);
141 }
142 
143 int findroot(int x)
144 {
145     access(x), splay(x);
146     pushdown(x);
147     while(lc) {
148         x = lc;
149         pushdown(x);
150     }
151     return x;
152 }
153 
154 int main()
155 {
156     N = read(), Q = read(); 
157     for(int i = 1; i <= N; i++) {
158         t[i].val = 1;
159     }
160     for(int i = 1; i <= Q; i++) {
161         scanf("%s", opr);
162         int x = read(), y = read();
163         if(opr[0] == 'A') {
164             link(x, y);
165         } else {
166             split(x, y);
167             LL ans = (t[x].size + 1) * (t[y].size + 1);
168             printf("%lld\n", ans);
169         }
170     }
171 }
View Code

 

转载于:https://www.cnblogs.com/wuenze/p/9151929.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值