BZOJ 4154 [Ipsc2015]Generating Synergy(KD-Tree)
题目链接:BZOJ 4154 [Ipsc2015]Generating Synergy
题意:
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色。
题解:
将dfs序看为x,dep看为y,那么就是一个在二维平面上的操作了。
由于这个平面范围比较大,二维线段树不好开,然后kd-tree搞搞。
1 #include<cstdio> 2 #include<algorithm> 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 6 namespace KD_Tree{ 7 const int N=1e5+7,DI=2; 8 struct Node{ 9 int p[DI],f,l,r,mx[DI],mi[DI],tim,col,t,c; 10 int operator[](const int&idx)const{return p[idx];} 11 void in(int idx,int *v){f=idx,tim=t=0,c=col=1;F(i,0,DI-1)p[i]=v[i];} 12 void up(Node&a){ 13 F(i,0,DI-1){ 14 mi[i]=min(mi[i],a.mi[i]); 15 mx[i]=max(mx[i],a.mx[i]); 16 } 17 } 18 }T[N]; 19 int idx[N],cmpd,root; 20 21 bool cmp(const Node&a,const Node&b){return a[cmpd]<b[cmpd];} 22 void up(int x){ 23 if(T[x].l)T[x].up(T[T[x].l]); 24 if(T[x].r)T[x].up(T[T[x].r]); 25 } 26 int build(int l,int r,int d=0,int f=0) 27 { 28 int mid=l+r>>1; 29 cmpd=d%DI,nth_element(T+l,T+mid,T+r+1,cmp); 30 idx[T[mid].f]=mid,T[mid].f=f; 31 F(i,0,DI-1)T[mid].mi[i]=T[mid].mx[i]=T[mid][i]; 32 T[mid].l=l!=mid?build(l,mid-1,d+1,mid):0; 33 T[mid].r=r!=mid?build(mid+1,r,d+1,mid):0; 34 return up(mid),mid; 35 } 36 void update(int x1,int x2,int y1,int y2,int t,int c,int rt=root) 37 { 38 if(T[rt].mi[0]>=x1&&T[rt].mx[0]<=x2&&T[rt].mi[1]>=y1&&T[rt].mx[1]<=y2) 39 { 40 T[rt].tim=t,T[rt].col=c; 41 T[rt].t=t,T[rt].c=c; 42 return; 43 } 44 if(T[rt].mx[0]<x1||T[rt].mi[0]>x2||T[rt].mx[1]<y1||T[rt].mi[1]>y2) 45 return; 46 if(T[rt][0]>=x1&&T[rt][0]<=x2&&T[rt][1]>=y1&&T[rt][1]<=y2) 47 T[rt].tim=t,T[rt].col=c; 48 if(T[rt].l)update(x1,x2,y1,y2,t,c,T[rt].l); 49 if(T[rt].r)update(x1,x2,y1,y2,t,c,T[rt].r); 50 } 51 int ask(int rt) 52 { 53 int t=T[rt].tim,c=T[rt].col; 54 while(T[rt].f) 55 { 56 rt=T[rt].f; 57 if(T[rt].t>t)t=T[rt].t,c=T[rt].c; 58 } 59 return c; 60 } 61 }; 62 const int N=1e5+7,P=1e9+7; 63 int t,n,q,g[N],v[N],nxt[N],ed,c; 64 int x,in[N],out[N],cnt,dep[N],ans; 65 66 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 67 68 void dfs(int x,int d=0) 69 { 70 in[x]=++cnt,dep[x]=d; 71 for(int i=g[x];i;i=nxt[i])dfs(v[i],d+1); 72 out[x]=++cnt; 73 } 74 75 using namespace KD_Tree; 76 int main(){ 77 scanf("%d",&t); 78 while(t--) 79 { 80 scanf("%d%d%d",&n,&c,&q); 81 F(i,1,n)g[i]=0;ed=0; 82 F(i,2,n)scanf("%d",&x),adg(x,i); 83 ans=0,cnt=0,dfs(1); 84 F(i,1,n) 85 { 86 int x[2]; 87 x[0]=in[i],x[1]=dep[i]; 88 T[i].in(i,x); 89 } 90 root=build(1,n); 91 F(i,1,q) 92 { 93 int a,l,c; 94 scanf("%d%d%d",&a,&l,&c); 95 if(c)update(in[a],out[a],dep[a],dep[a]+l,i,c); 96 else 97 { 98 int tmp=ask(idx[a]); 99 ans=(ans+1ll*tmp*i)%P; 100 } 101 } 102 printf("%d\n",ans); 103 } 104 return 0; 105 }