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 1HintIf 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.
Source
大致题意:
一棵树1e5节点的树,有1e5次两种操作,修改某点的权值,询问两点间的路径上的每个权值是否都是偶数个,若不是输出奇数个的权值大小,保证询问的路径上最多只有一个权值是奇数个
思路:
方法1.维护每个点到根的异或,然后查询就是xor[u]^xor[v]^LCA(u,v)
更新操作:更新某个点显然此点的子树的xor到根的异或都会更新,所以用dfs记录进入节点和退出节点的时间戳,把时间戳作为节点映射到线段树上(所以个数是数节点的两倍),然后成段更新进入此节点到退出此节点的时间戳的区间即可
复杂度是nlogn
方法2:
正面上,询问就是两个点间的路径的异或,即树链剖分
复杂度n*logn*logn
方法一:
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
const int N = 1e5+100;
int n,Q;
int indx;
struct Edge
{
int v,nxt;
Edge(){}
Edge(int v,int nxt):v(v),nxt(nxt){}
}es[N<<1];
int head[N],ecnt;
inline void add_edge(int v,int u)
{
es[ecnt] = Edge(v,head[u]);
head[u] = ecnt++;
es[ecnt] = Edge(u,head[v]);
head[v] = ecnt++;
}
int val[N];
//....................................
#define root 1,indx,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int XOR[N<<2];
inline void pushup(int rt)
{
XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
}
void update(int pos,int x,int l,int r,int rt)
{
if(l == r)
{
XOR[rt] ^= x;
return ;
}
int m = (l+r)>>1;
if(pos <= m) update(pos,x,lson);
else update(pos,x,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R) return XOR[rt];
int m = (l+r)>>1;
int ans = 0;
if(L <= m) ans ^= query(L,R,lson);
if(R > m) ans ^= query(L,R,rson);
return ans;
}
//.................................
int dep[N],hvyson[N],sz[N],fa[N];
void dfs1(int u)
{
dep[u] = dep[fa[u]]+1;
hvyson[u] = 0,sz[u] = 1;
for(int i = head[u];~i;i = es[i].nxt)
{
int v = es[i].v;
if(v == fa[u]) continue;
fa[v] = u;
dfs1(v);
sz[u] += sz[v];
if(sz[v] > sz[hvyson[u]]) hvyson[u] = v;
}
}
int tp[N],tid[N];
void dfs2(int u,int ance)
{
tid[u] = ++indx;
tp[u] = ance;
if(hvyson[u]) dfs2(hvyson[u],ance);
for(int i = head[u];~i;i = es[i].nxt)
{
int v = es[i].v;
if(v == fa[u]) continue;
if(v != hvyson[u])dfs2(v,v);
}
}
int ask(int u,int v)
{
int anceu = tp[u],ancev = tp[v];
int ans = 0;
while(anceu != ancev)
{
if(dep[anceu] < dep[ancev]) swap(anceu,ancev),swap(u,v);
ans ^= query(tid[anceu],tid[u],root);
u = fa[anceu];
anceu = tp[u];
}
if(u == v) return ans ^= val[u];
if(dep[u] < dep[v]) return ans ^= query(tid[u],tid[v],root);
else return ans ^= query(tid[v],tid[u],root);
}
//..................................
void ini()
{
ecnt = indx = 0;
memset(head,-1,sizeof(head));
memset(XOR,0,sizeof(XOR));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ini();
scanf("%d%d",&n,&Q);
REP(i,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
REP(i,n) scanf("%d",&val[i]),val[i]++;
dfs1(1);
dfs2(1,1);
REP(i,n) update(tid[i],val[i],root);
REP(i,Q)
{
int op;
scanf("%d",&op);
if(op == 0)
{
int u,x;
scanf("%d%d",&u,&x);x++;
update(tid[u],val[u]^x,root);
val[u] = x;
}
else
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",ask(u,v)-1);
}
}
}
}
方法二:
//312MS 21660K 4306 B C++
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
const int N = 1e5+100;
int n,Q;
struct Edge
{
int v,nxt;
Edge(){}
Edge(int v,int nxt) : v(v),nxt(nxt){}
}es[N*2];
int ecnt,head[N];
inline void add_edge(int u,int v)
{
es[ecnt] = Edge(v,head[u]);
head[u] = ecnt++;
es[ecnt] = Edge(u,head[v]);
head[v] = ecnt++;
}
int val[N];
//...................................
int indx,st[N],ed[N],vs[N<<1];
int dp[N];
void dfs(int u,int fa)
{
dp[u] = dp[fa]^val[u];
st[u] = ++indx;
vs[indx] = u;
for(int i = head[u];~i;i = es[i].nxt)
{
int v = es[i].v;
if(v == fa) continue;
dfs(v,u);
}
ed[u] = ++indx;
vs[indx] = u;
}
//...............................
int dep[N];
bool vis[N];
int pa[N][20];
void bfs()
{
queue<int>q;
q.push(1);
pa[1][0]=1;
vis[1]=1;
while(!q.empty())
{
int u=q.front(); q.pop();
for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1];
for(int i=head[u];~i;i=es[i].nxt)
{
int v=es[i].v;
if(vis[v]==0)
{
vis[v]=1;
pa[v][0]=u;
dep[v]=dep[u]+1;
q.push(v);
}
}
}
}
int LCA(int u,int v)
{
if(dep[u]>dep[v]) swap(u,v);
for(int det=dep[v]-dep[u],i=0;det;i++,det>>=1)
if(det&1) v=pa[v][i];
if(v==u) return v;
for(int i=20-1;i>=0;i--)
if(pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i];
return pa[u][0];
}
//...............................
int XOR[(N<<1)<<2],col[(N<<1)<<2];
#define root 1,indx,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
inline void pushup(int rt)
{
XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
}
inline void pushdown(int rt)
{
if(col[rt] == 0) return ;
col[rt<<1] ^= col[rt];
col[rt<<1|1] ^= col[rt];
XOR[rt<<1] ^= col[rt];
XOR[rt<<1|1] ^= col[rt];
col[rt] = 0;
}
void build(int l,int r,int rt)
{
if(l == r)
{
XOR[rt] = dp[vs[l]];
col[rt] = 0;
return ;
}
int m = (l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int x,int l,int r,int rt)
{
if(L <= l && r <= R)
{
XOR[rt] ^= x;
col[rt] ^= x;
return ;
}
pushdown(rt);
int m = (l+r)>>1;
if(L <= m) update(L,R,x,lson);
if(R > m) update(L,R,x,rson);
pushup(rt);
}
int query(int pos,int l,int r,int rt)
{
if(l == r) return XOR[rt];
pushdown(rt);
int m = (l+r)>>1;
if(pos <= m) return query(pos,lson);
else return query(pos,rson);
}
//..............................
void ini()
{
indx = ecnt = 0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ini();
scanf("%d%d",&n,&Q);
REP(i,n-1)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
REP(i,n) scanf("%d",&val[i]),val[i]++;
dfs(1,0);
bfs();
build(root);
while(Q--)
{
int op;
scanf("%d",&op);
if(op == 0)
{
int u,x;
scanf("%d%d",&u,&x);
x++;
update(st[u],ed[u],val[u]^x,root);
val[u] = x;
}
else
{
int u,v;
scanf("%d%d",&u,&v);
int ans = query(ed[u],root)^query(ed[v],root)^val[LCA(u,v)];
printf("%d\n",ans-1);
}
}
}
}