很厉害的题
orz了网上的题解,大家似乎都在orz雯舞,那我也赶紧Orz吧,前两天刚在BZOJ把我超了-_-orzorz
然后这题的话,先考虑没有深度的条件
先令每个点的贡献都是1,那么如果有同色点,他们的lca的贡献就要减一,而我们知道取dfs序相邻的两个点的话lca最深,所以令同色点dfs序相邻的点贡献-1,然后答案就是子树和
考虑深度限制,我们对于每一个i,维护只考虑所有深度<=i的点时的答案
考虑现在有深度为i时的答案,那么我们搞个主席树,然后把深度为i+1的点挨个插进来即可,插的时候用set维护一下每个颜色的dfs序,就可以搞了
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 100010
#define MAXM 10000010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct vec{
int to;
int fro;
};
struct data{
int p;
int x;
data(){
}
data(int _p,int _x){
p=_p;
x=_x;
}
friend bool operator <(data x,data y){
return x.p<y.p;
}
};
vec mp[MAXN];
int tai[MAXN],cnt;
int n,m;
int a[MAXN];
int fa[MAXN][20];
int dep[MAXN];
int siz[MAXN],dfn[MAXN],tim;
int p[MAXN];
int rt[MAXN];
int son[MAXM][2],v[MAXM];
int tot;
int la;
set<data>s[MAXN];
bool cmp(int x,int y){
return dep[x]<dep[y];
}
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
int lca(int x,int y){
int i;
if(dep[x]<dep[y]){
swap(x,y);
}
for(i=19;~i;i--){
if(dep[fa[x][i]]>=dep[y]){
x=fa[x][i];
}
}
for(i=19;~i;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return x==y?x:fa[x][0];
}
void dfs(int x){
int i,y;
dfn[x]=++tim;
siz[x]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
dfs(y);
siz[x]+=siz[y];
}
}
void change(int &x,int xx,int y,int z,int p,int cv){
x=++tot;
memcpy(son[x],son[xx],sizeof(son[x]));
v[x]=v[xx]+cv;
if(y==z){
return ;
}
int mid=y+z>>1;
if(p<=mid){
change(son[x][0],son[xx][0],y,mid,p,cv);
}else{
change(son[x][1],son[xx][1],mid+1,z,p,cv);
}
}
int ask(int x,int y,int z,int l,int r){
if(!x){
return 0;
}
if(y==l&&z==r){
return v[x];
}
int mid=y+z>>1;
if(r<=mid){
return ask(son[x][0],y,mid,l,r);
}else if(l>mid){
return ask(son[x][1],mid+1,z,l,r);
}else{
return ask(son[x][0],y,mid,l,mid)+ask(son[x][1],mid+1,z,mid+1,r);
}
}
int main(){
int i,j,x;
int tmp;
scanf("%d",&tmp);
while(tmp--){
memset(fa,0,sizeof(fa));
memset(tai,0,sizeof(tai));
cnt=0;
tim=0;
tot=0;
la=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
p[i]=i;
}
dep[1]=1;
for(i=2;i<=n;i++){
scanf("%d",&x);
be(x,i);
dep[i]=dep[x]+1;
for(j=0;x;j++){
fa[i][j]=x;
x=fa[x][j];
}
}
dfs(1);
int wzh=1;
sort(p+1,p+n+1,cmp);
for(i=1;i<=n;i++){
rt[i]=rt[i-1];
while(dep[p[wzh]]==i&&wzh<=n){
x=p[wzh];
change(rt[i],rt[i],1,n,dfn[x],1);
set<data>::iterator it=s[a[x]].insert(data(dfn[x],x)).first;
set<data>::iterator itt=it;
itt++;
if(it!=s[a[x]].begin()&&itt!=s[a[x]].end()){
set<data>::iterator tit=it;
tit--;
change(rt[i],rt[i],1,n,dfn[lca((*tit).x,(*itt).x)],1);
}
if(it!=s[a[x]].begin()){
set<data>::iterator tit=it;
tit--;
change(rt[i],rt[i],1,n,dfn[lca(x,(*tit).x)],-1);
}
if(itt!=s[a[x]].end()){
change(rt[i],rt[i],1,n,dfn[lca(x,(*itt).x)],-1);
}
wzh++;
}
}
while(m--){
scanf("%d%d",&i,&x);
//*
i^=la;
x^=la;
//*/
printf("%d\n",la=ask(rt[min(dep[i]+x,n)],1,n,dfn[i],dfn[i]+siz[i]-1));
}
for(i=1;i<=n;i++){
s[i].clear();
}
}
return 0;
}
/*
1
4 4
4 2 3 2
1 2 1
3 2
2 2
4 1
4 1
*/