您的位置:首页 > 其它

hdu 5274 Dylans loves tree (树链剖分+异或和)

2018-03-01 16:35 453 查看

Dylans loves tree

[b]Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1881    Accepted Submission(s): 477
[/b]

[align=left]Problem Description[/align]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 
[align=left]Input[/align]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). 
[align=left]Output[/align]For each question ② in each testcase,if the value all appear even times output "-1",otherwise output the value that appears odd times. 
[align=left]Sample Input[/align]
13 21 22 31 1 11 1 21 1 3 [align=left]Sample Output[/align]
-11HintIf 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息