HDU 4897 Little Devil I

Little Devil I

Time Limit: 8000ms
Memory Limit: 131072KB
This problem will be judged on  HDU. Original ID: 4897
64-bit integer IO format: %I64d      Java class name: Main
There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and can’t refuse any request from the devil. Also, this devil is looking like a very cute Loli.

The devil likes to make thing in chaos. This kingdom’s road system is like simply a tree(connected graph without cycle). A road has a color of black or white. The devil often wants to make some change of this system.

In details, we call a path on the tree from a to b consists of vertices lie on the shortest simple path between a and b. And we say an edge is on the path if both its two endpoints is in the path, and an edge is adjacent to the path if exactly one endpoint of it is in the path.

Sometimes the devil will ask you to reverse every edge’s color on a path or adjacent to a path.

The king’s daughter, WJMZBMR, is also a cute loli, she is surprised by her father’s lolicon-like behavior. As she is concerned about the road-system’s status, sometimes she will ask you to tell there is how many black edge on a path.

Initially, every edges is white.
 

Input

The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains an integer n, which is the size of the tree. The vertices be indexed from 1.
On the next n-1 lines, each line contains two integers a,b, denoting there is an edge between a and b. 
The next line contains an integer Q, denoting the number of the operations.
On the next Q lines, each line contains three integers t,a,b. t=1 means we reverse every edge’s color on path a to b. t=2 means we reverse every edge’s color adjacent to path a to b. t=3 means we query about the number of black edge on path a to b.

T<=5.
n,Q<=105.
Please use scanf,printf instead of cin,cout,because of huge input.
 

Output

For each t=3 operation, output the answer in one line.
 

Sample Input

1
10
2 1
3 1
4 1
5 1
6 5
7 4
8 3
9 5
10 6

10
2 1 6
1 3 8
3 8 10
2 3 4
2 10 8
2 4 10
1 7 6
2 7 3
2 1 4
2 10 10

Sample Output

3

Hint

reverse color means change from white to black or vice virsa.
 

Source

 
解题:树链剖分
  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 101010;
  4 struct arc {
  5     int to,next;
  6     arc(int x = 0,int y = -1) {
  7         to = x;
  8         next = y;
  9     }
 10 } e[maxn<<1];
 11 int head[maxn],cnt,tot;
 12 void add(int u,int v) {
 13     e[tot] = arc(v,head[u]);
 14     head[u] = tot++;
 15 }
 16 int dep[maxn],fa[maxn],top[maxn],siz[maxn],son[maxn];
 17 int loc[maxn],sum[maxn<<2],flip[maxn<<2],light[maxn<<2];
 18 void FindHeavyEdge(int u,int father,int depth) {
 19     dep[u] = depth;
 20     fa[u] = father;
 21     siz[u] = 1;
 22     son[u] = -1;
 23     for(int i = head[u]; ~i; i = e[i].next) {
 24         if(e[i].to == father) continue;
 25         FindHeavyEdge(e[i].to,u,depth + 1);
 26         siz[u] += siz[e[i].to];
 27         if(son[u] == -1 || siz[son[u]] < siz[e[i].to])
 28             son[u] = e[i].to;
 29     }
 30 }
 31 void ConnectHeavyEdge(int u,int ancestor){
 32     top[u] = ancestor;
 33     loc[u] = ++cnt;
 34     if(~son[u]) ConnectHeavyEdge(son[u],ancestor);
 35     for(int i = head[u]; ~i; i = e[i].next){
 36         if(e[i].to == fa[u] || e[i].to == son[u]) continue;
 37         ConnectHeavyEdge(e[i].to,e[i].to);
 38     }
 39 }
 40 inline void pushdown(int v,int L,int M,int R){
 41     if(flip[v]){
 42         flip[v<<1] ^= 1;
 43         flip[v<<1|1] ^= 1;
 44         sum[v<<1] = (M - L + 1) - sum[v<<1];
 45         sum[v<<1|1] = (R - M) - sum[v<<1|1];
 46         flip[v] = 0;
 47     }
 48     if(light[v]){
 49         light[v<<1] ^= 1;
 50         light[v<<1|1] ^= 1;
 51         light[v] = 0;
 52     }
 53 }
 54 inline void pushup(int v){
 55     sum[v] = sum[v<<1] + sum[v<<1|1];
 56 }
 57 void update(bool OP,int L,int R,int lt,int rt,int v){
 58     if(lt <= L && rt >= R){
 59         if(OP){
 60             flip[v] ^= 1;
 61             sum[v] = (R - L + 1) - sum[v];
 62         }else light[v] ^= 1;
 63         return;
 64     }
 65     int mid = (L + R)>>1;
 66     pushdown(v,L,mid,R);
 67     if(lt <= mid) update(OP,L,mid,lt,rt,v<<1);
 68     if(rt > mid) update(OP,mid + 1,R,lt,rt,v<<1|1);
 69     pushup(v);
 70 }
 71 int query(bool OP,int L,int R,int lt,int rt,int v){
 72     if(lt <= L && rt >= R) return OP?sum[v]:light[v];
 73     int ret = 0,mid = (L + R)>>1;
 74     pushdown(v,L,mid,R);
 75     if(lt <= mid) ret = query(OP,L,mid,lt,rt,v<<1);
 76     if(rt > mid) ret += query(OP,mid+1,R,lt,rt,v<<1|1);
 77     return ret;
 78 }
 79 void modifyHeavy(int u,int v){
 80     while(top[u] != top[v]){
 81         if(dep[top[u]] < dep[top[v]]) swap(u,v);
 82         update(true,1,cnt,loc[top[u]],loc[u],1);
 83         u = fa[top[u]];
 84     }
 85     if(u == v) return;
 86     if(dep[u] > dep[v]) swap(u,v);
 87     update(true,1,cnt,loc[son[u]],loc[v],1);
 88 }
 89 void modifyLight(int u,int v){
 90     while(top[u] != top[v]){
 91         if(dep[top[u]] < dep[top[v]]) swap(u,v);
 92         update(false,1,cnt,loc[top[u]],loc[u],1);
 93         if(~son[u]) update(true,1,cnt,loc[son[u]],loc[son[u]],1);
 94         update(true,1,cnt,loc[top[u]],loc[top[u]],1);
 95         u = fa[top[u]];
 96     }
 97     if(dep[u] > dep[v]) swap(u,v);
 98     update(false,1,cnt,loc[u],loc[v],1);
 99     if(fa[u]) update(true,1,cnt,loc[u],loc[u],1);
100     if(~son[v]) update(true,1,cnt,loc[son[v]],loc[son[v]],1);
101 }
102 int query(int u,int v,int ret = 0){
103     while(top[u] != top[v]){
104         if(dep[top[u]] < dep[top[v]]) swap(u,v);
105         if(u != top[u]) ret += query(true,1,cnt,loc[son[top[u]]],loc[u],1);
106         ret += query(true,1,cnt,loc[top[u]],loc[top[u]],1)^query(false,1,cnt,loc[fa[top[u]]],loc[fa[top[u]]],1);
107         u = fa[top[u]];
108     }
109     if(u == v) return ret;
110     if(dep[u] > dep[v]) swap(u,v);
111     return ret + query(true,1,cnt,loc[son[u]],loc[v],1);
112 }
113 int main() {
114     int kase,u,v,n,m,op;
115     scanf("%d",&kase);
116     while(kase--){
117         memset(head,-1,sizeof head);
118         memset(sum,0,sizeof sum);
119         memset(flip,0,sizeof flip);
120         memset(light,0,sizeof light);
121         cnt = tot = 0;
122         scanf("%d",&n);
123         for(int i = 1; i < n; ++i){
124             scanf("%d%d",&u,&v);
125             add(u,v);
126             add(v,u);
127         }
128         FindHeavyEdge(1,0,0);
129         ConnectHeavyEdge(1,1);
130         scanf("%d",&m);
131         while(m--){
132             scanf("%d%d%d",&op,&u,&v);
133             switch(op){
134                 case 1:modifyHeavy(u,v);break;
135                 case 2:modifyLight(u,v);break;
136                 case 3:printf("%d\n",query(u,v));break;
137                 default:;
138             }
139         }
140     }
141     return 0;
142 }
View Code

 

转载于:https://www.cnblogs.com/crackpotisback/p/4900658.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值