给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色。请写一个程序,快速回答这些询问。
强制在线
求题解跑
我比较懒,用set解决了前驱后继的操作
CODE:
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=500005;
int T;
int n,m;
int g[N];
struct qq
{
int x,y,last;
}e[N];int num,last[N];
void init (int x,int y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
int L[N],R[N],cnt;
int fa[N][21];
int dep[N];
int mx;
int belong[N];
void dfs (int x)
{
mx=max(mx,dep[x]);
L[x]=++cnt;for (int u=1;u<=20;u++) fa[x][u]=fa[fa[x][u-1]][u-1];
belong[cnt]=x;
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
dep[y]=dep[x]+1;
fa[y][0]=x;dfs(y);
}
R[x]=cnt;
}
int c[N*25],s1[N*25],s2[N*25];
int rt[N];
queue<int> q;
set<int> s[N];
int lca (int x,int y)
{
if (dep[x]>dep[y]) swap(x,y);
for (int u=20;u>=0;u--)
if (dep[fa[y][u]]>=dep[x])
y=fa[y][u];
if (x==y) return x;
for (int u=20;u>=0;u--)
if (fa[x][u]!=fa[y][u])
{
x=fa[x][u];y=fa[y][u];
}
return fa[x][0];
}
void change (int &now,int l,int r,int x,int xx)
{
if (now==0) {now=++num;c[now]=0;s1[now]=s2[now]=0;}
c[now]+=xx;
if (l==r) return ;
int mid=(l+r)>>1;
if (x<=mid) change(s1[now],l,mid,x,xx);
else change(s2[now],mid+1,r,x,xx);
}
set<int>::iterator a,b;
void Merge (int rt1,int &rt2)
{
if (rt1==0) return ;
if (rt2==0) {rt2=rt1;return ;}
c[rt2]+=c[rt1];
Merge(s1[rt1],s1[rt2]);
Merge(s2[rt1],s2[rt2]);
}
void solve ()
{
for (int u=1;u<=n;u++) s[u].clear();
num=0;q.push(1);
while (!q.empty())
{
int x=q.front(),d=dep[x];q.pop();
// printf("%d %d\n",x,d);
change(rt[d],1,n,L[x],1);
//printf("1:%d %d\n",d,x);
a=s[g[x]].lower_bound(L[x]);b=s[g[x]].upper_bound(L[x]);
if (a!=s[g[x]].begin())
{
int LCA=lca(belong[*(--a)],x);a++;
// printf("-1:d:%d lca:%d x:%d y:%d\n",d,LCA,belong[*(--a)],x);a++;
change(rt[d],1,n,L[LCA],-1);
}
if (b!=s[g[x]].end())
{
int LCA=lca(belong[*b],x);
// printf("-2:d:%d lca:%d x:%d y:%d\n",d,LCA,belong[*b],x);
change(rt[d],1,n,L[LCA],-1);
}
if (a!=s[g[x]].begin()&&b!=s[g[x]].end())
{
int LCA=lca(belong[*(--a)],belong[*b]);a++;
// printf("-3:d:%d lca:%d x:%d y:%d\n",d,LCA,belong[*(--a)],belong[*b]);a++;
change(rt[d],1,n,L[LCA],1);
}
s[g[x]].insert(L[x]);
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
q.push(y);
}
}
for (int u=2;u<=mx;u++) Merge(rt[u-1],rt[u]); //printf("NO\n");
}
int get (int now,int l,int r,int L,int R)
{
if (now==0) return 0;
// printf("%d %d %d\n",l,r,c[now]);
if (l==L&&r==R) return c[now];
int mid=(l+r)>>1;
if (R<=mid) return get(s1[now],l,mid,L,R);
else if (L>mid) return get(s2[now],mid+1,r,L,R);
else return get(s1[now],l,mid,L,mid)+get(s2[now],mid+1,r,mid+1,R);
}
int main()
{
scanf("%d",&T);
while (T--)
{
memset(rt,0,sizeof(rt));
num=0;memset(last,-1,sizeof(last));
cnt=0;
scanf("%d%d",&n,&m);
for (int u=1;u<=n;u++) scanf("%d",&g[u]);
for (int u=2;u<=n;u++)
{
int x;
scanf("%d",&x);
init(x,u);
}
mx=0;dep[1]=1;dfs(1);
//printf("YES\n");
/*for (int u=1;u<=n;u++) printf("%d ",L[u]);
printf("\n");*/
solve();
int ans=0;
for (int u=1;u<=m;u++)
{
int x,d;
scanf("%d%d",&x,&d);
x^=ans;d^=ans;
ans=get(rt[min(mx,dep[x]+d)],1,n,L[x],R[x]);
printf("%d\n",ans);
}
}
return 0;
}