bzoj 4154 Generating Synergy Posted on 2019-09-03 | Views: $kd$ 树. 将每个点的 $dfn,dep$ 视作 $x,y$ 坐标,那么每次修改就是给平面上一个矩形内的点染色. 用 $kd$ 树写一写,时间复杂度 $O(n\log n+q\sqrt n)$ . 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int P=1e9+7;inline int add(int a,int b){ return (a+b>=P)?(a+b-P):(a+b);}inline int mul(int a,int b){ return 1LL * a * b % P;}const int MAXN=1e5+10;const int inf=1e9;int ecnt=0,head[MAXN],to[MAXN],nx[MAXN];inline void addedge(int u,int v){ ++ecnt; to[ecnt]=v; nx[ecnt]=head[u]; head[u]=ecnt;}int dfn[MAXN],idx=0,siz[MAXN],dep[MAXN];void dfs(int u){ dfn[u]=++idx; siz[u]=1; for(int i=head[u];i;i=nx[i]) { int v=to[i]; dep[v]=dep[u]+1; dfs(v); siz[u]+=siz[v]; }}int n,C,Q,Tp;struct node{ int v[2],mx[2],mi[2],fa,id; int col,tag,ls,rs; node(){mx[0]=mx[1]=-inf,mi[0]=mi[1]=inf;} bool operator < (const node &rhs) const { return v[Tp]<rhs.v[Tp]; }}Tree[MAXN];#define root Tree[o]#define lson Tree[root.ls]#define rson Tree[root.rs]inline void pushup(int o){ for(int i=0;i<2;++i) { root.mx[i]=max(lson.mx[i],rson.mx[i]); root.mx[i]=max(root.mx[i],root.v[i]); root.mi[i]=min(lson.mi[i],rson.mi[i]); root.mi[i]=min(root.mi[i],root.v[i]); }}int pos[MAXN];int BuildTree(int l,int r,int tp){ Tp=tp; int mid=(l+r)>>1; int o=mid; nth_element(Tree+l,Tree+mid,Tree+r+1); pos[root.id]=o; if(l<=mid-1) { root.ls=BuildTree(l,mid-1,tp^1); lson.fa=o; } if(mid+1<=r) { root.rs=BuildTree(mid+1,r,tp^1); rson.fa=o; } pushup(o); return o;}inline void pushdown(int o){ if(root.tag) { if(root.ls) lson.col=lson.tag=root.tag; if(root.rs) rson.col=rson.tag=root.tag; root.tag=0; }}int Mx[2],Mi[2];void upd(int o,int c){ if(root.mi[0]>Mx[0] || root.mx[0]<Mi[0] || root.mi[1]>Mx[1] || root.mx[1]<Mi[1]) return; if(Mi[0]<=root.mi[0] && root.mx[0]<=Mx[0] && Mi[1]<=root.mi[1] && root.mx[1]<=Mx[1]) return (void)(root.col=root.tag=c); if(Mi[0]<=root.v[0] && root.v[0]<=Mx[0] && Mi[1]<=root.v[1] && root.v[1]<=Mx[1]) root.col=c; pushdown(o); if(root.ls) upd(root.ls,c); if(root.rs) upd(root.rs,c);}int stk[MAXN],tp;inline int query(int x){ tp=0; int y=x; while(Tree[y].fa) { stk[++tp]=Tree[y].fa; y=Tree[y].fa; } while(tp) pushdown(stk[tp--]); return Tree[x].col;}void solve(){ n=read(),C=read(),Q=read(); ecnt=0; idx=0; for(int i=1;i<=n;++i) head[i]=0; for(int i=2;i<=n;++i) addedge(read(),i); dfs(1); for(int i=1;i<=n;++i) { Tree[i].v[0]=dfn[i]; Tree[i].v[1]=dep[i]; Tree[i].ls=Tree[i].rs=0; Tree[i].col=1; Tree[i].tag=0; Tree[i].fa=0; Tree[i].id=i; } int rt=BuildTree(1,n,0); int ans=0; for(int i=1;i<=Q;++i) { int x=read(),y=read(),c=read(); if(!c) //query ans=add(ans,mul(i,query(pos[x]))); else //update { Mi[0]=dfn[x]; Mx[0]=dfn[x]+siz[x]-1; Mi[1]=dep[x]; Mx[1]=dep[x]+y; upd(rt,c); } } cout<<ans<<endl;}int main(){ int T=read(); while(T--) solve(); return 0;}