hdu 5274 Dylans loves tree (树链剖分 + 线段树 异或)
Dylans loves tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1915 Accepted Submission(s): 492
Problem Description
Dylans is given a tree with N nodes.
All nodes have a value A[i].Nodes on tree is numbered by 1∼N.
Then he is given Q questions like that:
①0 x y:change node x′s value to y
②1 x y:For all the value in the path from x to y,do they all appear even times?
For each ② question,it guarantees that there is at most one value that appears odd times on the path.
1≤N,Q≤100000, the value A[i]∈N and A[i]≤100000
All nodes have a value A[i].Nodes on tree is numbered by 1∼N.
Then he is given Q questions like that:
①0 x y:change node x′s value to y
②1 x y:For all the value in the path from x to y,do they all appear even times?
For each ② question,it guarantees that there is at most one value that appears odd times on the path.
1≤N,Q≤100000, the value A[i]∈N and A[i]≤100000
Input
In the first line there is a test number T.
(T≤3 and there is at most one testcase that N>1000)
For each testcase:
In the first line there are two numbers N and Q.
Then in the next N−1 lines there are pairs of (X,Y) that stand for a road from x to y.
Then in the next line there are N numbers A1..AN stand for value.
In the next Q lines there are three numbers(opt,x,y).
(T≤3 and there is at most one testcase that N>1000)
For each testcase:
In the first line there are two numbers N and Q.
Then in the next N−1 lines there are pairs of (X,Y) that stand for a road from x to y.
Then in the next line there are N numbers A1..AN stand for value.
In the next Q lines there are three numbers(opt,x,y).
Output
For each question ② in each testcase,if the value all appear even times output "-1",otherwise output the value that appears odd times.
Sample Input
1
3 2
1 2
2 3
1 1 1
1 1 2
1 1 3
Sample Output
-1
1
Hint
If you want to hack someone,N and Q in your testdata must smaller than 10000,and you shouldn't print any space in each end of the line.
思路:
一道非常简单的题。。要求u-v之前出现次数为奇数的数字,如果没找到就输出-1,找到就输出这个数字。
题目保证了出现为奇数次的数字的个数不超过1,那么直接对u-v异或就好了,最后剩下的如果是0有两种可能:
1.没有出现次数为奇数的数字 。 2.出现次数为奇数的数字为0;
我们只要将输入的数字全部+1就可以避免这种情况了
最后当输出的值为0时没有出现次数为奇数的数字,输出-1,不为0的话直接输出这个数字就好了。
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 2e5+10; struct node{ int to,next; }e[M]; int sum[M<<2],son[M],fa[M],head[M],siz[M],top[M],dep[M],tid[M],rk[M],a[M]; int cnt1,cnt,n; void add(int u,int v){ e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1; e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1; } void dfs1(int u,int faz,int deep){ dep[u] = deep; fa[u] = faz; siz[u] = 1; for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v != fa[u]){ dfs1(v,u,deep+1); siz[u] += siz[v]; if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(int u,int t){ top[u] = t; tid[u] = cnt; rk[cnt] = u; cnt++; if(son[u] == -1) return; dfs2(son[u],t); for(int i = head[u];i;i = e[i].next){ int v = e[i].to; if(v != son[u]&&v != fa[u]) dfs2(v,v); } } void pushup(int rt){ sum[rt] = sum[rt<<1]^sum[rt<<1|1]; } void build(int l,int r,int rt){ if(l == r){ sum[rt] = a[rk[l]]; return ; } mid; build(lson); build(rson); pushup(rt); } void update(int p,int c,int l,int r,int rt){ if(l == r){ sum[rt] = c; return ; } mid; if(p <= m) update(p,c,lson); else update(p,c,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return sum[rt]; } mid; int ret = 0; if(L <= m) ret^=query(L,R,lson); if(R > m) ret^=query(L,R,rson); return ret; } int ask(int x,int y){ int sum = 0; int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy); sum ^= query(tid[fx],tid[x],1,n,1); x = fa[fx];fx = top[x]; } if(dep[x] < dep[y]) swap(x,y); sum^=query(tid[y],tid[x],1,n,1); //cout<<sum<<endl; return sum; } void init() { memset(son,-1,sizeof(son)); for(int i = 0; i <= 2*n;i ++){ e[i].to = 0;e[i].next = 0;head[i] = 0; } } int main() { int t,u,v,x,y,op,q; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); cnt = 1; cnt1 = 1; init(); for(int i = 0; i < n-1;i ++){ scanf("%d%d",&u,&v); add(u,v); } for(int i = 1;i <= n;i ++) scanf("%d",&x),a[i]=x+1; dfs1(1,0,1); dfs2(1,1); build(1,n,1); while(q--){ scanf("%d",&op); if(op==1){ scanf("%d%d",&x,&y); //cout<<ask(x,y)<<endl; if(ask(x,y)!=0) printf("%d\n",ask(x,y)-1); else printf("-1\n"); } else{ scanf("%d%d",&x,&y); update(tid[x],y+1,1,n,1); } } } return 0; }