1. 程式人生 > >BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree

BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree

per algo printf desc element nbsp 維護 tdi cstring

BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree

Description

給定一棵以1為根的有根樹,初始所有節點顏色為1,每次將距離節點a不超過l的a的子節點染成c,或詢問點a的顏色

Input

第一行一個數T,表示數據組數 接下來每組數據的第一行三個數n,c,q表示結點個數,顏色數和操作數 接下來一行n-1個數描述2..n的父節點 接下來q行每行三個數a,l,c 若c為0,表示詢問a的顏色 否則將距離a不超過l的a的子節點染成c

Output

設當前是第i個操作,y_i為本次詢問的答案(若本次操作是一個修改則y_i為0),令z_i=i*y_i,請輸出z_1+z_2+...+z_q模10^9+7

Sample Input

1
4 3 7
1 2 2
3 0 0
2 1 3
3 0 0
1 0 2
2 0 0
4 1 1
4 0 0

Sample Output

32

HINT

第1,3,5,7的詢問的答案分別為1,3,3,1,所以答案為 1*1+2*0+3*3+4*0+5*3+6*0+7*1=32. 數據範圍: 對於100%的數據T<=6,n,m,c<=10^5, 1<=a<=n,0<=l<=n,0<=c<=c
設dfn[i]為i的dfs序的編號。 那麽每次相當於對所有dfn[x]<=dfn[y]<=son[x]且dep[y]-dep[x]<=L的點進行染色。 直接KDTree維護矩形染色即可。 代碼:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100050
#define ls ch[p][0]
#define rs ch[p][1]
typedef long long ll;
const int mod=1000000007;
int head[N],to[N<<1],nxt[N<<1],C[N],n,T;
int dfn[N],dep[N],mx[N][2],ch[N][2],mn[N][2],root,now,cov[N],son[N],cnt;
inline void add(int u,int v) {
	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
struct Point {
	int p[2];
	bool operator < (const Point &x) const {
		return p[now]==x.p[now]?p[!now]<x.p[!now]:p[now]<x.p[now];
	}
}a[N],b[N];
void pushup(int p,int x) {
	int i;
	for(i=0;i<2;i++) mx[p][i]=max(mx[p][i],mx[x][i]),mn[p][i]=min(mn[p][i],mn[x][i]);
}
void pushdown(int p) {
	if(cov[p]!=-1) {
		cov[ls]=cov[rs]=C[ls]=C[rs]=cov[p];
		cov[p]=-1;
	}
}
int build(int l,int r,int type) {
	int mid=(l+r)>>1; now=type;
	nth_element(a+l,a+mid,a+r+1);
	int i;
	for(i=0;i<2;i++) mx[mid][i]=mn[mid][i]=a[mid].p[i];
	if(l<mid) ch[mid][0]=build(l,mid-1,!type),pushup(mid,ch[mid][0]);
	if(r>mid) ch[mid][1]=build(mid+1,r,!type),pushup(mid,ch[mid][1]);
	return mid;
}
bool judge(int t1,int t2,int t3,int t4) {
	return (t1<t3||t1>t4)&&(t2<t3||t2>t4);
}
void update(int x,int y,int z,int w,int p,int c) {
	// printf("%d\n",p);
	// printf("%d %d %d %d\n",x,y,z,w);
	// a[x].mx[0] < bx || a[x].mn[0] > ex || a[x].mx[1] < by || a[x].mn[1] > ey
	if(mn[p][0]>=x&&mx[p][0]<=z&&mn[p][1]>=y&&mx[p][1]<=w) {cov[p]=C[p]=c; return ;}
	if(mx[p][0]<x||mn[p][0]>z||mx[p][1]<y||mn[p][1]>w) return ;
	pushdown(p);
	if(a[p].p[0]>=x&&a[p].p[0]<=z&&a[p].p[1]>=y&&a[p].p[1]<=w) C[p]=c;
	if(ls) update(x,y,z,w,ls,c);
	if(rs) update(x,y,z,w,rs,c);
}
int query(int x) {
	int p=root;
	now=0;
	while(1) {
		pushdown(p);
		if(b[x]<a[p]) p=ls;
		else if(a[p]<b[x]) p=rs;
		else return C[p];
		now=!now;
	}
}
void dfs(int x,int y) {
	int i;
	dfn[x]=++dfn[0];
	dep[x]=dep[y]+1;
	for(i=head[x];i;i=nxt[i]) {
		if(to[i]!=y) dfs(to[i],x);
	}
	son[x]=dfn[0];
}
void solve() {
	int Q;
	memset(head,0,sizeof(head)); cnt=0;
	memset(ch,0,sizeof(ch));
	dfn[0]=0;
	scanf("%d%*d%d",&n,&Q);
	int i,x,y;
	for(i=2;i<=n;i++) {
		scanf("%d",&x); add(x,i); add(i,x);
	}
	dfs(1,0);
	for(i=1;i<=n;i++) a[i].p[0]=dfn[i],a[i].p[1]=dep[i],cov[i]=-1,C[i]=1,b[i]=a[i];
	root=build(1,n,0);
	int ans=0,z;
	// printf("%d %d %d\n",dfn[4],son[4],dep[4]);
	for(i=1;i<=Q;i++) {
		scanf("%d%d%d",&x,&y,&z);
		if(z) {
			update(dfn[x],dep[x],son[x],dep[x]+y,root,z);
		}else {
			ans=(ans+ll(i)*query(x)%mod)%mod;
			// printf("%d\n",query(x));
		}
	}
	printf("%d\n",ans);
}
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		solve();
	}
}

BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree