[HDU5709]Claris Loves Painting
description
给定一棵\(n\)点的树,每个节点上有一个颜色,每次询问一个点的子树中与这个点距离不超过\(d\)的点的颜色有多少种。强制在线。
sol
对每个点开两棵线段树,一棵以颜色为下标,表示每种颜色出现的最浅深度,一棵以深度为下标,表示以该深度为最浅深度的颜色有多少种。
这两棵线段树都可以直接由儿子合并上来。
在合并前一棵线段树的时候可能会导致第二棵线段树的修改(两个节点颜色相同,那就要删除深度更大的点的贡献),处理一下即可。
复杂度\(O(n\log n)\)。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e5+5;
struct node{int ls,rs,w;}t[N*100];
int n,m,col[N],nxt[N],head[N],rt1[N],rt2[N],tot,dep[N],ans;
void build(int &x,int l,int r,int p,int v){
x=++tot;if (l==r) {t[x].w=v;return;}int mid=l+r>>1;
if (p<=mid) build(t[x].ls,l,mid,p,v);
else build(t[x].rs,mid+1,r,p,v);
}
void modify(int &x,int l,int r,int p,int v){
t[++tot]=t[x];t[x=tot].w+=v;if (l==r) return;int mid=l+r>>1;
if (p<=mid) modify(t[x].ls,l,mid,p,v);
else modify(t[x].rs,mid+1,r,p,v);
}
int merge_1(int x,int y,int l,int r,int u){
if (!x||!y) return x|y;int z=++tot,mid=l+r>>1;
if (l==r){
t[z].w=min(t[x].w,t[y].w);
modify(rt2[u],1,n,max(t[x].w,t[y].w),-1);
}
t[z].ls=merge_1(t[x].ls,t[y].ls,l,mid,u);
t[z].rs=merge_1(t[x].rs,t[y].rs,mid+1,r,u);
return z;
}
int merge_2(int x,int y){
if (!x||!y) return x|y;int z=++tot;t[z].w=t[x].w+t[y].w;
t[z].ls=merge_2(t[x].ls,t[y].ls);
t[z].rs=merge_2(t[x].rs,t[y].rs);
return z;
}
int query(int x,int l,int r,int ql,int qr){
if (l>=ql&&r<=qr) return t[x].w;int mid=l+r>>1,s=0;
if (ql<=mid) s+=query(t[x].ls,l,mid,ql,qr);
if (qr>mid) s+=query(t[x].rs,mid+1,r,ql,qr);
return s;
}
void dfs(int u){
build(rt1[u],1,n,col[u],dep[u]);modify(rt2[u],1,n,dep[u],1);
for (int v=head[u];v;v=nxt[v]){
dep[v]=dep[u]+1,dfs(v);
rt1[u]=merge_1(rt1[u],rt1[v],1,n,u);
rt2[u]=merge_2(rt2[u],rt2[v]);
}
}
int main(){
int Case=gi();while (Case--){
n=gi();m=gi();ans=0;
for (int i=1;i<=tot;++i) t[i]=(node){0,0,0};tot=0;
for (int i=1;i<=n;++i) col[i]=gi(),head[i]=rt1[i]=rt2[i]=0;
for (int i=2,f;i<=n;++i) nxt[i]=head[f=gi()],head[f]=i;
dep[1]=1;dfs(1);
while (m--){
int x=gi()^ans,d=gi()^ans;
printf("%d\n",ans=query(rt2[x],1,n,dep[x],dep[x]+d));
}
}
return 0;
}