BZOJ4771 七彩树

题目

给定一棵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的所有点中出现了多少种本质不同的颜色。请写一个程序,快速回答这些询问。

思路

本质与HDU3333Turing Tree是一样的,方法是可持久化线段树合并。

每个点开一个线段树,保存当前子树下每个深度的颜色数

再开一棵线段树,保存当前子树下每个颜色最浅的深度

在进行线段树合并时要注意当两棵树中存在相同颜色时,取较浅的一个,把深的颜色删去,代码比较难调。

需要注意的是,每次删除的操作都要新加节点,不能直接在原来的点上改,需要可持久化的思想。

代码

#include<bits/stdc++.h>
#define M 100005
#define clr(x,y) memset(x,y,sizeof(x))
using namespace std;
int T,n,m,A[M],h[M],tot,dep[M],inf;
struct edge{
	int nxt,to;
}G[M<<1];
void Add(int a,int b){
	G[++tot]=(edge){h[a],b};
	h[a]=tot;
}
int Lson[M*180],Rson[M*180],cnt[M*180],ver[M],tt;
void Insert1(int &p,int x,int d,int L,int R){
	cnt[++tt]=cnt[p];Lson[tt]=Lson[p];Rson[tt]=Rson[p];p=tt;	
	cnt[p]+=d;
	if(L==R)return;
	int mid=(L+R)>>1;
	if(x<=mid)Insert1(Lson[p],x,d,L,mid);
	else Insert1(Rson[p],x,d,mid+1,R);
}
void merge1(int& x,int y,int L,int R){
	if(!x||!y){x=(x|y);return;}
	cnt[++tt]=cnt[x];Lson[tt]=Lson[x];Rson[tt]=Rson[x];x=tt;
	if(L==R){cnt[x]+=cnt[y];return;}
	int mid=(L+R)>>1;
	merge1(Lson[x],Lson[y],L,mid);
	merge1(Rson[x],Rson[y],mid+1,R);
	cnt[x]=cnt[Lson[x]]+cnt[Rson[x]];
}
int query(int l,int r,int p,int L,int R){
//	cout<<l<<' '<<r<<' '<<p<<' '<<L<<' '<<R<<endl;
	if(!p)return 0;
	if(l==L&&r==R)return cnt[p];
	int mid=(L+R)>>1;
	if(r<=mid)return query(l,r,Lson[p],L,mid);
	else if(l>mid)return query(l,r,Rson[p],mid+1,R);
	return query(l,mid,Lson[p],L,mid)+query(mid+1,r,Rson[p],mid+1,R); 
}
int lson[M*25],rson[M*25],dp[M*25],rt[M],ttt;
void Insert2(int &p,int x,int d,int L,int R){
	if(!p)p=++ttt,lson[p]=rson[p]=0,dp[p]=1e9;
	if(L==R){dp[p]=min(dp[p],d);return;}
	int mid=(L+R)>>1;
	if(x<=mid)Insert2(lson[p],x,d,L,mid);
	else Insert2(rson[p],x,d,mid+1,R); 
}
void merge2(int &x,int y,int L,int R,int& p){
	if(!x||!y){x=(x|y);return;}
	if(L==R){
		Insert1(p,max(dp[x],dp[y]),-1,1,n);
		dp[x]=min(dp[x],dp[y]);
		return;
	}
	int mid=(L+R)>>1;
	merge2(lson[x],lson[y],L,mid,p);
	merge2(rson[x],rson[y],mid+1,R,p);
}
int last=0;
int main(){
	cin>>T;
	while(T--){
		clr(h,0);tot=ttt=tt=last=0;
		clr(rt,0);clr(ver,0);cnt[0]=0;dp[0]=1e9;Lson[0]=Rson[0]=lson[0]=rson[0]=0;
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)scanf("%d",&A[i]);
		dep[1]=1;
		for(int i=2,f;i<=n;i++)scanf("%d",&f),Add(f,i),dep[i]=dep[f]+1;
		for(int i=n;i>=1;i--){
			Insert1(ver[i],dep[i],1,1,n);
			Insert2(rt[i],A[i],dep[i],1,n);
			for(int j=h[i];j;j=G[j].nxt){
				int u=G[j].to;
				merge1(ver[i],ver[u],1,n);
				merge2(rt[i],rt[u],1,n,ver[i]);
			}
		}
		for(int i=1,x,d;i<=m;i++){
			scanf("%d%d",&x,&d);
			x=x^last;d=d^last;
			printf("%d\n",last=query(dep[x],min(n,dep[x]+d),ver[x],1,n));
		}
	}
	return 0;
}
posted @ 2019-02-08 16:36  zeroy0410  阅读(163)  评论(1编辑  收藏  举报