• 【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
    ",query(root,0));
    162             }
    163         }
    164         printf("%lld
    ",ans);
    165     }
    166 return 0;
    167 }
    View Code
  • 相关阅读:
    TCP 的那些事儿(下)
    如何获取(GET)一杯咖啡——星巴克REST案例分析
    前端必读:浏览器内部工作原理
    伟大的程序员是怎样炼成的?
    从用户行为打造活动交互设计闭环——2014年世界杯竞猜活动设计总结
    技术普及帖:你刚才在淘宝上买了一件东西
    什么是互联网思维?给你最全面的解释
    程序员生存定律-打造属于自己的稀缺性
    技术人员如何去面试?
    13幅逻辑图,领略杜克大学的经典思维
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/10023796.html
Copyright © 2020-2023  润新知