水题写挂系列----

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之间有一条边。

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

Data Constraint

对于40%的数据,N,Q≤1000

对于100%的数据,1≤N,Q≤100000
  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<vector>
  4 #include<map>
  5 #include<algorithm>
  6 #define maxn 300030
  7 using namespace std;
  8 struct node{
  9     int l;
 10     int r;
 11     int rmax;
 12     int tag;
 13     node* left;
 14     node* right;
 15     int val;
 16 }e1[maxn *5];
 17 int ttop = -1;
 18 int fw[maxn];
 19 inline void pushdown(node* x){
 20     if(!x->left || !x->right){
 21         return;
 22     }
 23     if(!x->tag){
 24         return;
 25     }
 26     x->left->val += x->tag * (x->left->r - x->left->l +1);
 27     x->left->tag += x->tag;
 28     x->right->val += x->tag * (x->right->r - x->right->l + 1);
 29     x->right->tag += x->tag;
 30     x->tag = 0;
 31 }
 32 inline void update(node* cur){
 33     cur->val = cur->left->val +cur->right->val;
 34     if(cur->right->rmax == cur->right->r - cur->right->l + 1){
 35         cur->rmax = cur->left->rmax + cur->right->rmax;
 36     }
 37     else{
 38         cur->rmax = cur->right->rmax;
 39     }
 40 }
 41 node* root;
 42 node* build(int l,int r){
 43     node* cur = &e1[++ttop];
 44     cur->l = l;
 45     cur->r = r;
 46     if(l == r){
 47         cur->val = 0;
 48           return cur;
 49     }
 50     int mid = (l+r) >>1;
 51     cur->left = build(l,mid);
 52     cur->right = build(mid+1,r);
 53     update(cur);
 54     return cur;
 55 }
 56 int find(node* cur,int l,int r){
 57     pushdown(cur);
 58     if(cur->l == l && cur->r == r){
 59         return cur->rmax;
 60     }
 61     int mid = (cur->l + cur->r) >>1;
 62     if(r <= mid){
 63         return find(cur->left,l,r);
 64     }
 65     else if( l > mid){
 66         return find(cur->right,l,r);
 67     }
 68     else{
 69         int lxl1 = find(cur->left,l,mid);
 70         int lxl2 = find(cur->right,mid+1,r);
 71         if(lxl2 == r - mid){
 72             return lxl1+lxl2;
 73         }
 74         else{
 75             return lxl2;
 76         }
 77     }
 78 }
 79 int get(node* cur,int pos){
 80     pushdown(cur);
 81     if(cur->l == cur->r){
 82         return cur->val;
 83     }
 84     int mid = (cur->l + cur->r) >>1;
 85     if(pos <= mid){
 86         return get(cur->left,pos);
 87     }
 88     else{
 89         return get(cur->right,pos);
 90     }
 91 }
 92 void modify2(node* cur,int pos){
 93     pushdown(cur);
 94     if(cur->l == cur->r){
 95         cur->rmax = 1;
 96         return;
 97     }
 98     int mid = (cur->l + cur->r) >>1;
 99     if(pos <= mid){
100         modify2(cur->left,pos);
101     }
102     else{
103         modify2(cur->right,pos);
104     }
105     update(cur);
106 }
107 void modify1(node* cur,int pos){
108     pushdown(cur);
109     if(cur->l == cur->r){
110         cur->val = 1;
111         return;
112     }
113     int mid = (cur->l + cur->r) >>1;
114     if(pos <= mid){
115         modify1(cur->left,pos);
116     }
117     else{
118         modify1(cur->right,pos);
119     }
120     update(cur);
121 }
122 void modify(node* cur,int l,int r,int va){
123     pushdown(cur);
124     if(cur->l == l && cur->r == r){
125         cur->val += va * (cur->r - cur->l + 1);
126         cur->tag += va;
127         return;
128     }
129     int mid = (cur->l + cur->r) >>1;
130     if(r <= mid){
131         modify(cur->left,l,r,va);
132     }
133     else if(l > mid){
134         modify(cur->right,l,r,va);
135     }
136     else{
137         modify(cur->left,l,mid,va);
138         modify(cur->right,mid+1,r,va);
139     }
140     update(cur);
141 }
142 struct edge {
143     int np;
144     int next;
145 } e[maxn];
146 int top2 =1;
147 int head[maxn];
148 inline void add(int x,int y) {
149     e[++top2] = (edge) {
150         y,head[x]
151     };
152     head[x] = top2;
153     e[++top2] = (edge) {
154         x,head[y]
155     };
156     head[y] = top2;
157 }
158 
159 int fa[maxn];
160 int deep[maxn];
161 int size[maxn];
162 int son[maxn];
163 int top[maxn];
164 int w[maxn];
165 int mp[maxn];
166 bool mark[maxn];
167 int hroot;
168 void dfs1(int x) {
169     int sizesum =1;
170     int sizetmp = 0;
171     int cur;
172     for(int i = head[x]; i; i = e[i].next) {
173         cur = e[i].np;
174         if(!deep[cur]) {
175             deep[cur] = deep[x] + 1;
176             fa[cur] = x;
177             dfs1(cur);
178             sizesum += size[cur];
179             if(size[cur] > sizetmp) {
180                 sizetmp = size[cur];
181                 son[x] = cur;
182             }
183         }
184     }
185     size[x] = sizesum;
186 }
187 int index = 0;
188 inline void initd2() {
189     deep[hroot] = 1;
190     top[hroot] = hroot;
191     w[hroot] = ++index;
192     fa[hroot] = 0;
193 }
194 void dfs2(int x,int top1) {
195     if(son[x] != 0) {
196         top[son[x]] = top1;
197         w[son[x]] = ++index;
198         dfs2(son[x],top1);
199     }
200     int cur;
201     for(int i =head[x]; i; i = e[i].next) {
202         cur = e[i].np;
203         if(cur != son[x] && cur != fa[x]) {
204             top[cur] = cur;
205             w[cur] = ++index;
206             dfs2(cur,cur);
207         }
208     }
209 }
210 void update1(int u){
211     if(u == 7){
212         int hjah = 0;
213     }
214     int nowadd = get(root,w[u]);
215     int fu;
216     modify(root,w[u],w[u],-nowadd);
217     do{
218         fu = top[u];
219         int len = 0;
220         if(w[fu]+1 <= w[u]){
221             len = find(root,w[fu]+1,w[u]);
222         }
223         if(len == w[u] - w[fu]){
224             modify(root,w[fu],w[u],nowadd);
225             if(find(root,w[fu],w[fu])){
226                 u = fa[fu];
227             }
228             else{
229                 break;
230             }
231         }
232         else{
233             int idlast = w[u] - len;
234             modify(root,idlast,w[u],nowadd);
235             break;
236         }
237     }while(u != 0);
238 }
239 struct line{
240     int l;
241     int r;
242     //int id;
243 };
244 struct qu{
245     line now;
246     int type;
247 }zqq[maxn];
248 int n;
249 int a,b,c;
250 int q;
251 int op;
252 int get_r_id(int u){
253     int fu = top[u];
254     do{
255         int len = 0;
256         if(w[fu] + 1 <= w[u]){
257             len = find(root,w[fu]+1,w[u]);
258         }
259         if(len == w[u]-w[fu]){
260             if(find(root,w[fu],w[fu])){
261                 u = fa[fu];    
262             }
263             else{
264                 return w[fu];
265             }
266         }
267         else{
268             return w[u] - len;
269         }
270     }while( u != 0);
271     if(u == hroot){
272         return w[hroot];
273     }
274 }
275 int pre[maxn];
276 int mark2[maxn];
277 int get_pre(int a){
278     int tmp = a;
279     while(a != pre[a]){
280         a = pre[a];
281     }
282     while(tmp != pre[tmp]){
283         pre[tmp] = a;
284         tmp = pre[tmp];
285     }
286     return a;
287 }
288 void un(int a,int b){
289     int haha1 = get_pre(a);
290     int haha2 = get_pre(b);
291     pre[haha1] = haha2;
292 }
293 int main(){
294     freopen("333.in","r",stdin);
295     freopen("my.out","w",stdout);
296     scanf("%d %d",&n,&q);
297     bool flag = true;
298     for(int i =0;i<=n;i++){
299         pre[i] = i;
300     }
301     for(int i =1;i<=q;i++){
302         a = getchar();
303         while(a == ' '|| a == '\n'){
304             a = getchar();
305         }
306         scanf("%d %d",&b,&c);
307         if(a == 'A'){
308             if(flag){
309                 flag = false;
310                 hroot = b;
311             }
312             zqq[i].now = (line){b,c};
313             add(b,c);
314             un(b,c);
315             zqq[i].type = 1;
316         }
317         else{
318             zqq[i].now = (line){b,c};
319             zqq[i].type = 0;
320         }
321     }
322     int p_root = get_pre(hroot);
323     for(int i =1;i<=n;i++){
324         int cyz = get_pre(i);
325         if(cyz != p_root && !mark2[cyz]){
326             mark2[cyz] = 1;
327             add(cyz,hroot);
328         }
329     }
330     initd2();
331     dfs1(hroot);
332     dfs2(hroot,hroot);
333     root = build(1,index);
334     for(int i =1;i<=q;i++){
335         int tmp1 = zqq[i].now.l;
336         int tmp2 = zqq[i].now.r;
337         if(!mark[tmp1]){
338             modify1(root,w[tmp1]);
339             mark[tmp1] = 1;
340         }
341         if(!mark[tmp2]){
342             modify1(root,w[tmp2]);
343             mark[tmp2] = 1;
344         }
345         if(i == 1){
346             modify2(root,w[zqq[i].now.r]);
347             update1(zqq[i].now.r);
348             continue;
349         }
350         if(zqq[i].type == 1){
351             tmp1 = zqq[i].now.l;
352             tmp2 = zqq[i].now.r;
353             mark[tmp1] = mark[tmp2] = 1;
354             if(fa[tmp1] == tmp2){
355                 modify2(root,w[tmp1]);
356                 update1(tmp1);
357             }
358             else{
359                 modify2(root,w[tmp2]);
360                 update1(tmp2);
361             }
362         }
363         else{
364             tmp1 = zqq[i].now.l;
365             tmp2 = zqq[i].now.r;
366             if(tmp1 == 7 && tmp2 == 8){
367                 int hahas = 0;
368             }
369             int nowrootid;
370             if(fa[tmp1] == tmp2){
371                 nowrootid = get_r_id(tmp2);
372                 int sizetot = get(root,nowrootid);
373                 int sizea = get(root,w[tmp1]);
374                 int sizeb = sizetot - sizea;
375                 printf("%d\n",sizea * sizeb);
376             }
377             else{
378                 nowrootid = get_r_id(tmp1);
379                 int sizetot = get(root,nowrootid);
380                 int sizea = get(root,w[tmp2]);
381                 int sizeb = sizetot - sizea;
382                 printf("%d\n",sizea * sizeb);
383             }
384         }
385     }
386 }

首先离线链剖(把最后的树的形态确定。。主要如果有多个互不相交的树要自己补全为一棵树)

唉。。太丑原谅。。。毕竟考试的时候边界挂了。。。线段树维护每个节点的子树的size。。每次加入一条边就维护下连通性(线段树上把这条边改为1)。。我是用线段树维护每个区间从右开始的连续为1的最大的长度。。直接get_r_id求出当前的这个点所在的联通块的root。。然后在连边的时候更新你连上之后并入新联通块之后新联通块里从这个点开始到联通块root这条链上的每个点的子树size。。(线段树区间修改)。查询答案就先找到这条边的father和儿子的关系。然后get_r_id找到father所在联通块的顶点。得到这个联通块的siz然后再找到son的子树的大小。。答案就是(当前联通块大小-son子树大小)*son子树大小。。。

 

虽然有可以用并茶几维护联通块的

posted @ 2016-03-18 19:31  cx_oier  阅读(126)  评论(0编辑  收藏  举报