【BZOJ4154】Generating Synergy【kd树】

题意

  给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色

分析

  我们以dfs序为横坐标,深度为纵坐标,建kd树。我们每次更新,都是在kd树中更新一个矩形,横坐标为[st[a],en[a]],纵坐标[depth[a],depth[a]+l]。那么就相当于线段树的区间更新,我们需要给它打个标记。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 const int maxn=1e5+100;
  9 const int INF=2147483647;
 10 const int mod=1e9+7;
 11 
 12 int n,q,c,sz,T;
 13 int head[maxn],Next[2*maxn],to[2*maxn];
 14 int cnt;
 15 int order[maxn],indx[maxn],st[maxn],en[maxn],depth[maxn];
 16 struct kdNode{
 17     int x[2],mnn[2],mxn[2];
 18     int lc,rc,u;
 19     int val,tag;
 20 }p[maxn],x;
 21 int cmpNo,root;
 22 int cmp(kdNode a,kdNode b){
 23     return a.x[cmpNo]<b.x[cmpNo];
 24 }
 25 void pushdown(int o){
 26     if(p[o].tag){
 27         int l=p[o].lc,r=p[o].rc;
 28         p[l].val=p[o].tag,p[r].val=p[o].tag;
 29         p[o].tag=0;
 30     }
 31 }
 32 
 33 void maintain(int o){
 34     int l=p[o].lc,r=p[o].rc;
 35     for(int i=0;i<2;i++){
 36         p[o].mnn[i]=min(min(p[l].mnn[i],p[r].mnn[i]),p[o].x[i]);
 37         p[o].mxn[i]=max(max(p[l].mxn[i],p[r].mxn[i]),p[o].x[i]);
 38     }
 39 }
 40 void build(int &o,int l,int r,int d){
 41     if(l>r){
 42         o=0;
 43         return;
 44     }
 45     int m=l+(r-l)/2;
 46     p[m].tag=0;
 47     cmpNo=d,o=m;
 48     nth_element(p+l,p+m,p+r+1,cmp);
 49     build(p[o].lc,l,m-1,d^1);
 50     build(p[o].rc,m+1,r,d^1);
 51     maintain(o);
 52 }
 53 bool all(int o){
 54     if(p[o].mxn[0]<=x.mxn[0]&&p[o].mnn[0]>=x.mnn[0]&&p[o].mnn[1]>=x.mnn[1]&&p[o].mxn[1]<=x.mxn[1]){
 55         return true;
 56     }
 57     return false;
 58 }
 59 bool have(int o){
 60     if(p[o].mnn[o]<=x.mxn[0]&&p[o].mxn[o]>=x.mnn[0]&&p[o].mxn[1]>=x.mnn[1]&&p[o].mnn[1]<=x.mxn[1]){
 61         return true;
 62     }
 63     return false;
 64 }
 65 void update(int o){
 66     if(!o)return;
 67     if(all(o)){
 68         p[o].tag=x.tag;
 69         p[o].val=x.tag;
 70         return;
 71     }
 72 
 73     pushdown(o);
 74     int l=p[o].lc,r=p[o].rc;
 75     if(p[o].x[0]>=x.mnn[0]&&p[o].x[0]<=x.mxn[0]&&p[o].x[1]>=x.mnn[1]&&p[o].x[1]<=x.mxn[1]){
 76         p[o].val=x.tag;
 77     }
 78     if(all(l)){
 79         p[l].tag=p[l].val=x.tag;
 80     }else if(have(l)){
 81         update(l);
 82     }
 83     if(all(r)){
 84         p[r].tag=p[r].val=x.tag;
 85     }else if(have(r)){
 86         update(r);
 87     }
 88 }
 89 int query(int o){
 90     if(!o)return 0;
 91     if(p[o].u==x.u){
 92         return p[o].val;
 93     }
 94     pushdown(o);
 95     int l=p[o].lc,r=p[o].rc;
 96 
 97     if(p[l].mnn[0]<=x.x[0]&&p[l].mxn[0]>=x.x[0]&&x.x[1]>=p[l].mnn[1]&&x.x[1]<=p[l].mxn[1])
 98         return query(l);
 99     else
100         return query(r);
101 }
102 void init(){
103     sz=0;
104     cnt=0;
105     memset(head,-1,sizeof(head));
106 }
107 void add_edge(int a,int b){
108     ++sz;
109     to[sz]=b;
110     Next[sz]=head[a];
111     head[a]=sz;
112 }
113 void dfs(int u,int fa,int dep){
114     depth[u]=dep;
115     order[++cnt]=u;
116     indx[u]=cnt;
117     st[u]=cnt;
118     for(int i=head[u];i!=-1;i=Next[i]){
119         int v=to[i];
120         if(v==fa)
121             continue;
122         dfs(v,u,dep+1);
123     }
124     en[u]=cnt;
125 }
126 int main(){
127     scanf("%d",&T);
128     for(int kase=1;kase<=T;kase++){
129         scanf("%d%d%d",&n,&c,&q);
130         init();
131         for(int i=2;i<=n;i++){
132             int fa;
133             scanf("%d",&fa);
134             add_edge(fa,i);
135             add_edge(i,fa);
136         }
137         dfs(1,-1,1);
138         for(int i=1;i<=n;i++){
139             p[i].x[0]=indx[i];
140             p[i].x[1]=depth[i];
141             p[i].u=i;
142             p[i].val=1;
143             p[i].tag=p[i].lc=p[i].rc=0;
144         }
145         p[0].mnn[0]=p[0].mnn[1]=INF;
146         p[0].mxn[0]=p[0].mxn[1]=-INF;
147         build(root,1,n,0);
148         LL ans=0;
149         for(int i=1;i<=q;i++){
150             int a,l,c;
151             scanf("%d%d%d",&a,&l,&c);
152             if(c){
153                 x.mnn[0]=st[a],x.mxn[0]=en[a],x.tag=c;
154                 x.mnn[1]=depth[a],x.mxn[1]=depth[a]+l;
155                 update(root);
156             }else{
157                 x.u=a;
158                 x.x[0]=indx[a];
159                 x.x[1]=depth[a];
160                 ans=(ans+(LL)i*query(root))%mod;
161 //                printf("%d\n",query(root,0));
162             }
163         }
164         printf("%lld\n",ans);
165     }
166 return 0;
167 }
View Code

 

posted @ 2018-11-26 23:21  蒟蒻LQL  阅读(193)  评论(0编辑  收藏  举报