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 }
View Code

 

posted @ 2017-08-07 18:30  bin_gege  阅读(107)  评论(0编辑  收藏  举报