[题解] 七彩树

题意

一棵以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;
}
posted @ 2021-12-29 07:32  sitiy  阅读(61)  评论(1编辑  收藏  举报