ADAAPPLE - Ada and Apple
Ada the Ladybug is currently on a trip on apple tree. There are many apples on the tree connected with branches. Each apple is inhabited by either Psylloideas or by Woolly Apple Aphids. Psylloideas and Aphids doesn't like each other, so it is strictly prohibited to walk from apple of Psylloideas to apple of aphids (and vice versa). Ada has some questions, whether it is possible to go from node I to node J.
Anyway note, that as Aphids and Psyllodeas doesn't like each other, they sometime conquer an apple of the others. Also note, that it is a real apple tree (not some bush) so no apple is connected with more than 50 other apples.
Input
The first line contains 1 ≤ N, Q ≤ 3*105 , number apples on tree and number for queries.
The next line contains N characters (either 0 or 1), indicating whether ith apple belongs to Psyllodeas or to Aphids.
Next N-1 lines contains two numbers, the branches (edges) of apple tree (0 ≤ I, J < N, I ≠ J).
Each of following Q lines contains one of following types of queries:
0 I, 0 ≤ I < N, meaning that ownership of Ith apple has changed.
1 I J, 0 ≤ I, J < N, question, whether it is possible to go from Ith to Jth apple.
Output
For each query of second kind (1) print "YES", if it is possible or "NO" if it is impossible!
Example Input
8 11 00111100 0 1 1 7 1 2 2 3 2 6 2 4 4 5 1 1 2 1 0 7 1 6 5 1 2 3 1 6 7 0 2 1 1 2 1 0 7 1 6 5 1 2 3 1 6 7
Example Output
NO YES NO YES NO YES YES NO NO YES
题意:一棵树,点的权值只有0和1两种情况,询问树上两点之间的路径是否全为0或全为1。路径操作很容易想到树链刨分,树链刨分后,形成多段连续区间,用线段树维护查询这些区间即可。
#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
int n,q,indx;
int info[MAXN],a[MAXN],nd[MAXN],father[MAXN],dn[MAXN];
vector<int> to,nxt;
struct node{
int v,left,right;
}tree[4*MAXN];
void addedge(int a,int b)
{
to.push_back(b);
nxt.push_back(info[a]);
info[a]=to.size()-1;
}
void build(int id,int L,int R)
{
tree[id].left=L,tree[id].right=R;
if(L==R)
{
tree[id].v=a[dn[L]];
return;
}
int mid=(tree[id].left+tree[id].right)/2;
build(id*2,L,mid);
build(id*2+1,mid+1,R);
tree[id].v=tree[id*2].v+tree[id*2+1].v;
}
void update(int id,int pos)
{
if(tree[id].right==pos&&tree[id].left==pos)
{
tree[id].v=1-tree[id].v;
return;
}
int mid=(tree[id].left+tree[id].right)/2;
if(pos<=mid)
update(id*2,pos);
else if(pos>mid)
update(id*2+1,pos);
tree[id].v=tree[id*2].v+tree[id*2+1].v;
}
int query(int id,int L,int R)
{
if(tree[id].left==L&&tree[id].right==R)
return tree[id].v;
int mid=(tree[id].left+tree[id].right)/2;
if(mid<L)
return query(id*2+1,L,R);
else if(mid>=R)
return query(id*2,L,R);
else
return query(id*2,L,mid)+query(id*2+1,mid+1,R);
}
int dep[MAXN],heavyson[MAXN],size[MAXN];
void dfs1(int u,int fa)
{
father[u]=fa;
dep[u]=dep[fa]+1;
size[u]=1;
heavyson[u]=0;
int mmax=0;
for(int i=info[u];i!=-1;i=nxt[i])
{
int v=to[i];
if(v!=fa)
{
dfs1(v,u);
size[u]+=size[v];
if(size[v]>mmax)
{
heavyson[u]=v;
mmax=size[v];
}
}
}
}
int tp[MAXN];
void dfs2(int u,int ance)
{
nd[u]=++indx;
dn[indx]=u;
tp[u]=ance;
if(heavyson[u])
dfs2(heavyson[u],ance);
for(int i=info[u];i!=-1;i=nxt[i])
{
int v=to[i];
if(v!=father[u]&&v!=heavyson[u])
dfs2(v,v);
}
}
bool ask(int u,int v)
{
int anceu=tp[u],ancev=tp[v];
int ans=0,sum=0;
while(anceu!=ancev)
{
if(dep[anceu]<dep[ancev])
{
swap(anceu,ancev);
swap(u,v);
}
sum+=nd[u]-nd[anceu]+1;
ans+=query(1,nd[anceu],nd[u]);
u=father[anceu];
anceu=tp[u];
}
if(dep[u]<dep[v])
swap(u,v);
sum+=nd[u]-nd[v]+1;
ans+=query(1,nd[v],nd[u]);
if(ans==sum||ans==0)
return true;
else
return false;
}
void init()
{
indx=0;dep[0]=0;
memset(info,-1,sizeof(info));
to.clear();
nxt.clear();
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
getchar();
for(int i=1;i<=n;i++)
{
char c=getchar();
a[i]=c-'0';
}
getchar();
init();
for(int i=0;i<n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u+1,v+1);
addedge(v+1,u+1);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i=0;i<q;i++)
{
int op,x,y;
scanf("%d",&op);
if(op==0)
{
scanf("%d",&x);
a[x+1]=1-a[x+1];
update(1,nd[x+1]);
}
else
{
scanf("%d%d",&x,&y);
if(ask(x+1,y+1))
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}