题意
一棵以1为根n个节点的树,每个点有颜色\(c_i\in[1,n]\)
m个询问,给定x,d,求x的子树内深度在\([dep_x,dep_x+d]\)的节点的颜色种类数
强制在线,多组数据
题解
这个若没有深度限制就能转化成dfs序,然后主席树就可了
既然有深度限制,考虑可持久化线段树,每个深度一个版本
在加入深度为x这一层时,设加的点v,先在v的dfn上加1
若c[v]出现过,则要将v的祖先中,深度最深的有c[v]这种颜色的点减1
具体来说就是维护n个set,st[i]存颜色为 i 的点的dfn值
加入v时找到st[c[v]]里的前驱pre和后继suf,找到lca(pre,v)和lca(suf,v)里深度深的加上-1就行了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+11;
struct tree{int lc,rc,sum;}tre[80*N];
struct st_{int dfn,x;friend bool operator<(st_ a,st_ b){return a.dfn<b.dfn;}};
int n,m;
int root[N],tot;
int c[N];
int dep[N];
int L[N],num,R[N];
int f[20][N],pg[N];
set<st_> st[N];
set<st_>::iterator it;
vector<int> cc[N],vct[N];
inline int read()
{
int s=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s;
}
void dfs(int x)
{
for(int i=1;i<=pg[dep[x]];++i) f[i][x]=f[i-1][f[i-1][x]];
L[x]=++num;
vct[dep[x]].push_back(x);
for(int v : cc[x])
{
f[0][v]=x;
dep[v]=dep[x]+1;
dfs(v);
}
R[x]=num;
return;
}
int get_lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=pg[dep[x]-dep[y]];i>=0;--i) if(dep[f[i][x]]>=dep[y])x=f[i][x];
if(x==y) return x;
for(int i=pg[dep[x]];i>=0;--i) if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];
return f[0][x];
}
void insert(int &i,int j,int l,int r,int x,int val)
{
i=++tot;
tre[i]=tre[j],tre[i].sum+=val;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) insert(tre[i].lc,tre[j].lc,l,mid,x,val);
else insert(tre[i].rc,tre[j].rc,mid+1,r,x,val);
return;
}
int query(int i,int l,int r,int x,int y)
{
if(l>=x&&r<=y) return tre[i].sum;
int mid=(l+r)>>1;
int ans=0;
if(x<=mid) ans=query(tre[i].lc,l,mid,x,y);
if(y>mid) ans+=query(tre[i].rc,mid+1,r,x,y);
return ans;
}
void init()
{
for(int i=1;i<=tot;++i) tre[i]={0,0,0};
tot=num=0;
for(int i=1;i<=n;++i)
{
root[i]=0;
for(int j=1;j<=19;++j) f[j][i]=0;
vct[i].clear();
st[i].clear();
cc[i].clear();
}
return;
}
int main()
{
int t=read();
while(t--)
{
init();
for(int i=1;i<=1e5;++i) pg[i]=log2(i);
n=read();
m=read();
for(int i=1;i<=n;++i) c[i]=read();
for(int x,i=2;i<=n;++i) x=read(),cc[x].push_back(i);
dep[1]=1;
dfs(1);
for(int lcap,lcan,i=1;i<=n;++i)
{
root[i]=root[i-1];
for(int v : vct[i])
{
lcap=lcan=0;
insert(root[i],root[i],1,n,L[v],1);
if(st[c[v]].size()==0){st[c[v]].insert({L[v],v});continue;}
it=st[c[v]].upper_bound({L[v],v});
if(it!=st[c[v]].end()) lcan=get_lca(v,(*it).x),insert(root[i],root[i],1,n,L[lcan],-1);
if(it!=st[c[v]].begin()) --it,lcap=get_lca(v,(*it).x),insert(root[i],root[i],1,n,L[lcap],-1);
if(lcan&&lcap) insert(root[i],root[i],1,n,L[get_lca(lcap,lcan)],1);
st[c[v]].insert({L[v],v});
}
}
for(int x,d,ans=0,i=1;i<=m;++i)
{
x=read()^ans;
d=read()^ans;
printf("%d\n",ans=query(root[dep[x]+d],1,n,L[x],R[x]));
}
}
return 0;
}