欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ4154: [Ipsc2015]Generating Synergy【KD树(懒标记)】

程序员文章站 2022-07-14 13:37:56
...

题目描述:

给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色。
T<=6,n,m,c<=10^5,1<=a<=n,0<=l<=n,0<=c<=c

题目分析:

n+e的题解:
BZOJ4154: [Ipsc2015]Generating Synergy【KD树(懒标记)】

Code:

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
const int mod = 1e9+7;
int T,n,m,out[maxn],dfn[maxn],tim,dep[maxn];
vector<int>G[maxn];
void dfs(int u){
	dfn[u]=++tim;
	for(int i=G[u].size()-1,v;i>=0;i--) dep[v=G[u][i]]=dep[u]+1,dfs(v);
	out[u]=tim;
}
int rt,id[maxn],ans,x[2],y[2];
struct node{
	int d[2],mn[2],mx[2],ch[2],col,tag;
	void upd(node *t){
		mn[0]=mx[0]=d[0],mn[1]=mx[1]=d[1];
		for(int i=0;i<2;i++) if(ch[i])
			for(int j=0;j<2;j++) mn[j]=min(mn[j],t[ch[i]].mn[j]),mx[j]=max(mx[j],t[ch[i]].mx[j]);
	}
}t[maxn];
template<int D>bool cmp(int i,int j){return t[i].d[D]==t[j].d[D]?t[i].d[D^1]<t[j].d[D^1]:t[i].d[D]<t[j].d[D];}
bool (*fun[2])(int i,int j)={cmp<0>,cmp<1>};
void build(int &i,int l,int r,int D){
	if(l>r) return void(i=0);
	int o=(l+r)>>1;nth_element(id+l,id+o,id+r+1,fun[D]),i=id[o];
	build(t[i].ch[0],l,o-1,D^1),build(t[i].ch[1],o+1,r,D^1);
	t[i].upd(t);
}
inline void pushdown(int i){
	if(t[i].tag){
		int x=t[i].ch[0];if(x) t[x].col=t[x].tag=t[i].tag;
		if((x=t[i].ch[1])) t[x].col=t[x].tag=t[i].tag;
		t[i].tag=0;
	}
}
void cover(int i,int c){
	if(!i||x[1]<t[i].mn[0]||t[i].mx[0]<x[0]||y[1]<t[i].mn[1]||t[i].mx[1]<y[0]) return;
	if(x[0]<=t[i].mn[0]&&t[i].mx[0]<=x[1]&&y[0]<=t[i].mn[1]&&t[i].mx[1]<=y[1]) {t[i].col=t[i].tag=c;return;}
	if(x[0]<=t[i].d[0]&&t[i].d[0]<=x[1]&&y[0]<=t[i].d[1]&&t[i].d[1]<=y[1]) t[i].col=c;
	pushdown(i);
	cover(t[i].ch[0],c),cover(t[i].ch[1],c);
}
int qry(int i,int j,int D){
	if(i==j) return t[i].col;
	pushdown(i);
	return qry(t[i].ch[fun[D](i,j)],j,D^1);
}
int main()
{
	scanf("%d",&T);
	while(T--){
		scanf("%d%*d%d",&n,&m),ans=tim=0;
		for(int i=1;i<=n;i++) G[i].clear();
		for(int i=2,x;i<=n;i++) scanf("%d",&x),G[x].push_back(i);
		dfs(1);
		for(int i=1;i<=n;i++) id[i]=i,t[i].d[0]=dfn[i],t[i].d[1]=dep[i],t[i].col=1,t[i].tag=0;
		build(rt,1,n,0);
		for(int i=1,a,b,c;i<=m;i++){
			scanf("%d%d%d",&a,&b,&c);
			if(!c) ans=(ans+1ll*i*qry(rt,a,0))%mod;
			else x[0]=dfn[a],x[1]=out[a],y[0]=dep[a],y[1]=dep[a]+b,cover(rt,c);
		}
		printf("%d\n",ans);
	}
}
相关标签: KD树