[HDU5709]Claris Loves Painting

vjudge

description

给定一棵\(n\)点的树,每个节点上有一个颜色,每次询问一个点的子树中与这个点距离不超过\(d\)的点的颜色有多少种。强制在线。

sol

对每个点开两棵线段树,一棵以颜色为下标,表示每种颜色出现的最浅深度,一棵以深度为下标,表示以该深度为最浅深度的颜色有多少种。
这两棵线段树都可以直接由儿子合并上来。
在合并前一棵线段树的时候可能会导致第二棵线段树的修改(两个节点颜色相同,那就要删除深度更大的点的贡献),处理一下即可。
复杂度\(O(n\log n)\)

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 1e5+5;
struct node{int ls,rs,w;}t[N*100];
int n,m,col[N],nxt[N],head[N],rt1[N],rt2[N],tot,dep[N],ans;
void build(int &x,int l,int r,int p,int v){
	x=++tot;if (l==r) {t[x].w=v;return;}int mid=l+r>>1;
	if (p<=mid) build(t[x].ls,l,mid,p,v);
	else build(t[x].rs,mid+1,r,p,v);
}
void modify(int &x,int l,int r,int p,int v){
	t[++tot]=t[x];t[x=tot].w+=v;if (l==r) return;int mid=l+r>>1;
	if (p<=mid) modify(t[x].ls,l,mid,p,v);
	else modify(t[x].rs,mid+1,r,p,v);
}
int merge_1(int x,int y,int l,int r,int u){
	if (!x||!y) return x|y;int z=++tot,mid=l+r>>1;
	if (l==r){
		t[z].w=min(t[x].w,t[y].w);
		modify(rt2[u],1,n,max(t[x].w,t[y].w),-1);
	}
	t[z].ls=merge_1(t[x].ls,t[y].ls,l,mid,u);
	t[z].rs=merge_1(t[x].rs,t[y].rs,mid+1,r,u);
	return z;
}
int merge_2(int x,int y){
	if (!x||!y) return x|y;int z=++tot;t[z].w=t[x].w+t[y].w;
	t[z].ls=merge_2(t[x].ls,t[y].ls);
	t[z].rs=merge_2(t[x].rs,t[y].rs);
	return z;
}
int query(int x,int l,int r,int ql,int qr){
	if (l>=ql&&r<=qr) return t[x].w;int mid=l+r>>1,s=0;
	if (ql<=mid) s+=query(t[x].ls,l,mid,ql,qr);
	if (qr>mid) s+=query(t[x].rs,mid+1,r,ql,qr);
	return s;
}
void dfs(int u){
	build(rt1[u],1,n,col[u],dep[u]);modify(rt2[u],1,n,dep[u],1);
	for (int v=head[u];v;v=nxt[v]){
		dep[v]=dep[u]+1,dfs(v);
		rt1[u]=merge_1(rt1[u],rt1[v],1,n,u);
		rt2[u]=merge_2(rt2[u],rt2[v]);
	}
}
int main(){
	int Case=gi();while (Case--){
		n=gi();m=gi();ans=0;
		for (int i=1;i<=tot;++i) t[i]=(node){0,0,0};tot=0;
		for (int i=1;i<=n;++i) col[i]=gi(),head[i]=rt1[i]=rt2[i]=0;
		for (int i=2,f;i<=n;++i) nxt[i]=head[f=gi()],head[f]=i;
		dep[1]=1;dfs(1);
		while (m--){
			int x=gi()^ans,d=gi()^ans;
			printf("%d\n",ans=query(rt2[x],1,n,dep[x],dep[x]+d));
		}
	}
	return 0;
}
posted @ 2018-07-31 22:34  租酥雨  阅读(425)  评论(0编辑  收藏  举报