题目
建两棵动态开点权值线段树。
一棵以颜色为下标,维护每种颜色出现的最浅深度。
一棵以深度为下标,维护以该深度为最浅深度的颜色有多少种。
然后dfs的时候启发式合并线段树即可。

#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define pb push_back
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');}
}
using namespace IO;
int min(int a,int b){return a<b? a:b;}
int max(int a,int b){return a>b? a:b;}
const int N=100007;
int col[N],nxt[N],head[N],root1[N],root2[N],dep[N],ans,n,m,cnt;
struct node{int l,r,x;}t[N*100];
vector<int>G[N];
void build(int &p,int l,int r,int x,int v)
{
    p=++cnt;
    if(l==r) return t[p].x=v,void();
    x<=mid? build(t[p].l,l,mid,x,v):build(t[p].r,mid+1,r,x,v);
}
void update(int &p,int l,int r,int x,int v)
{
    t[++cnt]=t[p],t[p=cnt].x+=v;
    if(l==r) return ;
    x<=mid? update(t[p].l,l,mid,x,v):update(t[p].r,mid+1,r,x,v);
}
int query(int p,int l,int r,int L,int R)
{
    if(L<=l&&r<=R) return t[p].x;
    return (L<=mid? query(t[p].l,l,mid,L,R):0)+(R>mid? query(t[p].r,mid+1,r,L,R):0);
}
int merge1(int u,int v,int l,int r,int x)
{
    if(!u||!v) return u|v;
    int p=++cnt;
    if(l==r) t[p].x=min(t[u].x,t[v].x),update(root2[x],1,n,max(t[u].x,t[v].x),-1);
    t[p].l=merge1(t[u].l,t[v].l,l,mid,x),t[p].r=merge1(t[u].r,t[v].r,mid+1,r,x);
    return p;
}
int merge2(int u,int v)
{
    if(!u||!v) return u|v;
    int p=++cnt;
    t[p]=(node){merge2(t[u].l,t[v].l),merge2(t[u].r,t[v].r),t[u].x+t[v].x};
    return p;
}
void dfs(int u)
{
    build(root1[u],1,n,col[u],dep[u]),update(root2[u],1,n,dep[u],1);
    for(int i=0,v;i<G[u].size();++i) dep[v=G[u][i]]=dep[u]+1,dfs(v),root1[u]=merge1(root1[u],root1[v],1,n,u),root2[u]=merge2(root2[u],root2[v]);
}
int main()
{
    for(int T=read(),i,x,d,ans;T;--T)
    {
        n=read(),m=read(),ans=0;
        for(i=1;i<=cnt;++i) t[i]=(node){0,0,0};
        for(cnt=0,i=1;i<=n;++i) col[i]=read(),root1[i]=root2[i]=0,G[i].clear();
        for(i=2;i<=n;++i) x=read(),G[x].pb(i);
        dep[1]=1;dfs(1);
        while(m--) x=read()^ans,d=read()^ans,write(ans=query(root2[x],1,n,dep[x],dep[x]+d));
    }
    return Flush(),0;
}
01-25 14:20