【KD树】BZOJ 4154 [Ipsc2015]Generating Synergy

【题目】
给定一棵以 1 1 1为根的有根树,初始所有节点颜色为 1 1 1,每次将距离节点 a a a不超过 l l l a a a的子节点染成 c c c,或询问点 a a a的颜色。
n ≤ 1 0 5 n\leq 10^5 n105

【解题思路】
dfs \text{dfs} dfs序作为一维,深度作为一维,直接上 KD \text{KD} KD树即可。

【参考代码】

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10,mod=1e9+7;

int read()
{
	int ret=0;char c=getchar();
	while(!isdigit(c)) c=getchar();
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return ret;
}

namespace Data_Structure
{
	struct coor
	{
		int x,y;
		coor(int _x=0,int _y=0):x(_x),y(_y){}
		friend coor gmax(const coor&a,const coor&b){return coor(max(a.x,b.x),max(a.y,b.y));}
		friend coor gmin(const coor&a,const coor&b){return coor(min(a.x,b.x),min(a.y,b.y));}
	}a[N],b[N];
	bool cmpx(const coor&a,const coor&b){return a.x<b.x || (a.x==b.x && a.y<b.y);}
	bool cmpy(const coor&a,const coor&b){return a.y<b.y || (a.y==b.y && a.x<b.x);}
	struct node
	{
		coor mx,mi,p;
		int col,cov,lc,rc;
	};
	struct KDT
	{
		#define ls t[x].lc
		#define rs t[x].rc
		int rt,sz;node t[N];
		void build(int &x,int l,int r,int D=0)
		{
			x=++sz;int mid=(l+r)>>1;
			nth_element(b+l,b+mid,b+r+1,D?cmpx:cmpy);
			t[x].p=t[x].mx=t[x].mi=b[mid];t[x].col=1;t[x].cov=0;ls=rs=0;
			if(l<mid) build(ls,l,mid-1,D^1),t[x].mx=gmax(t[x].mx,t[ls].mx),t[x].mi=gmin(t[x].mi,t[ls].mi);
			if(r>mid) build(rs,mid+1,r,D^1),t[x].mx=gmax(t[x].mx,t[rs].mx),t[x].mi=gmin(t[x].mi,t[rs].mi);
			//printf("%d %d %d %d %d %d %d %d %d\n",x,l,r,t[x].p.x,t[x].p.y,t[x].mi.x,t[x].mx.x,t[x].mi.y,t[x].mx.y);
		}
		int inmp(const coor&l,const coor&r,int xl,int xr,int yl,int yr)
		{
			if(xl<=l.x && r.x<=xr && yl<=l.y && r.y<=yr) return 1;
			if(r.x<xl || l.x>xr || r.y<yl || l.y>yr) return -1;
			return 0;
		}
		void pushdown(int x)
		{
			if(t[x].cov) t[ls].cov=t[rs].cov=t[ls].col=t[rs].col=t[x].cov,t[x].cov=0;
		}
		void update(int x,int xl,int xr,int yl,int yr,int c)
		{
			if(!x) return;
			pushdown(x);int v=inmp(t[x].mi,t[x].mx,xl,xr,yl,yr);
			//printf("%d %d %d %d %d %d %d %d\n",x,t[x].p.x,t[x].p.y,xl,xr,yl,yr,v);
			if(!~v) return;
			if(v) {t[x].cov=t[x].col=c;return;}
			if(inmp(t[x].p,t[x].p,xl,xr,yl,yr)==1) t[x].col=c;
			update(ls,xl,xr,yl,yr,c);update(rs,xl,xr,yl,yr,c);
		}
		int query(int x,int l,int r)
		{
			//cerr<<x<<" "<<l<<" "<<r<<" "<<t[x].p.x<<" "<<t[x].p.y<<" "<<t[x].mi.x<<" "<<t[x].mx.x<<" "<<t[x].mi.y<<" "<<t[x].mx.y<<endl;
			if(!x) return 0;
			pushdown(x);
			if(!~inmp(t[x].mi,t[x].mx,l,l,r,r)) return 0;
			if(t[x].p.x==l && t[x].p.y==r) return t[x].col;
			return query(ls,l,r)+query(rs,l,r);
		}
		#undef ls
		#undef rs
	}T;
}
using namespace Data_Structure;

namespace DreamLolita
{
	int n,C,Q,ind,tot,ans;
	int head[N],st[N],ed[N],dep[N],fa[N];
	struct Tway{int v,nex;}e[N];
	void add(int u,int v){e[++tot]=(Tway){v,head[u]};head[u]=tot;}
	void dfs(int x)
	{
		st[x]=++ind;
		for(int i=head[x];i;i=e[i].nex) dep[e[i].v]=dep[x]+1,dfs(e[i].v);
		ed[x]=ind;
	}
	void clear()
	{
		tot=ind=T.sz=T.rt=ans=0;
		for(int i=1;i<=n;++i) head[i]=0;
	}
	void solution()
	{
		n=read();C=read();Q=read();
		for(int i=2;i<=n;++i) fa[i]=read(),add(fa[i],i);
		dep[1]=1;dfs(1);
		for(int i=1;i<=n;++i) a[i]=b[i]=coor(st[i],dep[i]);
		T.build(T.rt,1,n);
		for(int i=1;i<=Q;++i)
		{
			int x=read(),l=read(),c=read();
			//cerr<<x<<" "<<l<<" "<<c<<endl;
			//cerr<<st[x]<<" "<<ed[x]<<" "<<dep[x]<<" "<<a[x].x<<" "<<a[x].y<<endl;
			if(!c) ans=(ans+1ll*i*T.query(T.rt,a[x].x,a[x].y)%mod)%mod;
			else T.update(T.rt,st[x],ed[x],dep[x],dep[x]+l,c);
		}
		printf("%d\n",ans);
		clear();
	}
}

int main()
{
#ifdef Durant_Lee
	freopen("BZOJ4154.in","r",stdin);
	freopen("BZOJ4154.out","w",stdout);
#endif
	int T=read();
	while(T--) DreamLolita::solution();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值