【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 }