HDU - 5709 Claris Loves Painting line segment tree dynamic open point + merge

Title Link: https://cn.vjudge.net/problem/HDU-5709

Given an n-point tree, each node has a color. How many kinds of colors are there in the subtree of a point that is not more than d away from this point

Explanation:

Build two line segment trees for each node

t1[x] maintains the number of colors within [l,r] in the subtree of X. the same color is only calculated once, and the one with the lowest depth is taken

t2[x] maintains the minimum depth of each color in the subtree of X

Merge from the bottom to the top. t1 merges directly first. When t2 merges, if the same color appears, the one with the smaller depth will be reserved, and the one with the larger depth in t1 will be deleted. When querying, sum directly in the corresponding t1. As for the complexity, O((n+m)logn) is used. It feels that the constant should be very large. As for how big the memory is, let's look at the restrictions. Look at the others who are big Most of them are about 1e7, mainly to see that the n is about 1e5, which gives a lot of time. Just try it.

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
int t1[N],t2[N];
int f[N],c[N],d[N];
int rson[N*110],lson[N*110],val[N*110];
int tot;
int newnode()
{
	tot++;
	lson[tot]=0;
	rson[tot]=0;
	val[tot]=0;
	return tot;
}
int update(int pre,int l,int r,int pos,int v)
{
	int cur=newnode();
	val[cur]=val[pre]+v;
	lson[cur]=lson[pre];
	rson[cur]=rson[pre];
	if(l==r)return cur;
	int mid=(l+r)>>1;
	if(pos<=mid) lson[cur]=update(lson[pre],l,mid,pos,v);
	else rson[cur]=update(rson[pre],mid+1,r,pos,v);
	return cur;
}
int merge1(int x,int y,int l,int r)
{
	if(!x || !y) return x + y;
	int cur=newnode();
	val[cur]=val[x]+val[y];
	if(l==r)return cur;
	int mid=(r+l)>>1;
	lson[cur]=merge1(lson[x],lson[y],l,mid);
	rson[cur]=merge1(rson[x],rson[y],mid+1,r);
	return cur;
}
int merge2(int x,int y,int l,int r,int u)
{
	if(!x || !y) return x + y;
	int cur=newnode();
	if(l==r)
	{
		val[cur]=min(val[x],val[y]);
		if(val[x]<val[y])t1[u]=update(t1[u],1,n,val[y],-1);
		else t1[u]=update(t1[u],1,n,val[x],-1);
		return cur;
	}
	int mid=(r+l)>>1;
	lson[cur]=merge2(lson[x],lson[y],l,mid,u);
	rson[cur]=merge2(rson[x],rson[y],mid+1,r,u);
	return cur;
}
int query(int p,int l,int r,int rt)
{
	if(rt==0)return 0;
	if(r<=p) return val[rt];
	int mid=(r+l)>>1;
	int res=0;
	res+=query(p,l,mid,lson[rt]);
	if(p>mid)  res+=query(p,mid+1,r,rson[rt]);
	return res;
}
int main()
{
	int T,nn=1;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		tot=0;
		for(int i=1;i<=n;i++)scanf("%d",&c[i]);
		for(int i=2;i<=n;i++)scanf("%d",&f[i]);
		for(int i=1;i<=n;i++) d[i]=d[f[i]]+1;
		for(int i=1;i<=n;i++)
		{
			t1[i]=update(0,1,n,d[i],1);
			t2[i]=update(0,1,n,c[i],d[i]);
		}
		for(int i=n;i>1;i--)
		{
			t1[f[i]]=merge1(t1[f[i]],t1[i],1,n);
			t2[f[i]]=merge2(t2[f[i]],t2[i],1,n,f[i]);
		}
		int ans=0;
		int u,dep;
		while(m--)
		{
			scanf("%d%d",&u,&dep);
	//		cout<<ans<<"==\n";
			u^=ans;
			dep^=ans;
			printf("%d\n",ans=query(min(d[u]+dep,n),1,n,t1[u]));
		}
	}
	return 0;
}

 

Posted by volant on Fri, 15 Nov 2019 07:41:21 -0800