Dylans loves tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1881 Accepted Submission(s): 477
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
13 21 22 31 1 11 1 21 1 3
Sample Output
-11
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.
题意:
给你一棵树,n-1条边,每个点的权值,还有q个询问,
当询问id==0时,改变x点的权值为y
id==1时,输出x->y路径上,权值出现奇数次的权值(题目保证这个答案最多只有1个)
解析:
首先这里用树链剖分优化
这里有奇数次,且答案保证唯一,刚好满足异或的性质,所以我们只要维护异或和的线段树就可以了。
并且这里答案为0时存在特殊情况,要处理一下
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1e5+10;
const int ZERO = 1000001;
#define INF 1147483647
#define M(a) memset(a,0,sizeof(a))
int val[MAXN],fa[MAXN],dep[MAXN],siz[MAXN],id[MAXN],top[MAXN],ran[MAXN],son[MAXN];
typedef struct ee
{
int u,v;
int next;
}ee;
ee edge[MAXN*2];
int head[MAXN],cnt;
int num,n;
typedef struct node
{
int ii;
int sum;
}node;
node Btree[MAXN*4];
void addedge(int u,int v)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void dfs1(int x,int f,int d)
{
dep[x]=d;
siz[x]=1;
son[x]=0;
fa[x]=f;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int tmp=edge[i].v;
if(tmp==f) continue;
dfs1(tmp,x,d+1);
siz[x]+=siz[tmp];
if(siz[son[x]]<siz[tmp])
{
son[x]=tmp;
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
id[x]=++num;
ran[num]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int tmp=edge[i].v;
if(tmp==fa[x]||tmp==son[x]) continue;
dfs2(tmp,tmp);
}
}
void Pushup(int root)
{
Btree[root].sum=Btree[2*root].sum^Btree[2*root+1].sum;
}
void build(int stu[],int l,int r,int root)
{
if(l>r) return;
if(l==r)
{
Btree[root].ii=l;
Btree[root].sum=stu[ran[l]];
return;
}
int mid=(l+r)/2;
build(stu,l,mid,root*2);
build(stu,mid+1,r,root*2+1);
Pushup(root);
}
void update(int root,int l,int r,int index,int val)
{
if(l>r) return;
if(l==r)
{
if(l==index)
{
Btree[root].sum=val;
}
return;
}
int mid=(l+r)/2;
if(index<=mid)
update(root*2,l,mid,index,val);
else
update(root*2+1,mid+1,r,index,val);
Pushup(root);
}
int querysum(int root,int l,int r,int s,int e)
{
if(r<s||l>e)
{
return 0;
}
if(l>r) return 0;
if(s<=l&&r<=e)
{
return Btree[root].sum;
}
int mid=(l+r)/2;
int lan=querysum(2*root,l,mid,s,e);
int ran=querysum(root*2+1,mid+1,r,s,e);
return lan^ran;
}
int solvesum(int a,int b)
{
if(dep[top[a]]<dep[top[b]])
{
swap(a,b);
}
int ans=0;
while(top[a]!=top[b])
{
//int tmp=top[a];
ans^=querysum(1,1,n,id[top[a]],id[a]);
a=fa[top[a]];
if(dep[top[a]]<dep[top[b]])
{
swap(a,b);
}
}
if(id[a]>id[b]) swap(a,b);
ans^=querysum(1,1,n,id[a],id[b]);
if(ans==ZERO) printf("0\n");
else if(ans==0) printf("-1\n");
else printf("%d\n",ans);
}
int main()
{
int q,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
num=0;
M(Btree);
M(son);
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
if(val[i]==0) val[i]=ZERO;
}
dfs1(1,0,1);
dfs2(1,1);
int mode,a,b;
build(val,1,n,1);
for(int i=0;i<q;i++)
{
scanf("%d%d%d",&mode,&a,&b);
if(mode==0)
{
val[a]=b;
update(1,1,n,id[a],b);
}
else if(mode==1)
{
solvesum(a,b);
}
}
}
return 0;
}