zoukankan      html  css  js  c++  java
  • BZOJ4154:[Ipsc2015]Generating Synergy(K-D Tree)

    Description

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

    Input

    第一行一个数T,表示数据组数
    接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数
    接下来一行n-1个数描述2..n的父节点
    接下来q行每行三个数a,l,c
    若c为0,表示询问a的颜色
    否则将距离a不超过l的a的子节点染成c

    Output

    设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+...+z_q模10^9+7

    Sample Input

    1
    4 3 7
    1 2 2
    3 0 0
    2 1 3
    3 0 0
    1 0 2
    2 0 0
    4 1 1
    4 0 0

    Sample Output

    32

    HINT

    第1,3,5,7的询问的答案分别为1,3,3,1,所以答案为 1*1+2*0+3*3+4*0+5*3+6*0+7*1=32.
    数据范围:
    对于100%的数据T<=6,n,m,c<=10^5,
    1<=a<=n,0<=l<=n,0<=c<=c

    Solution

    将每个点看成二维点$(DFN[x],Depth[x])$,也就是$DFS$序和深度。

    这样的话这个题就变成了单点查询和区间打标记覆盖了。

    区间打标记的时候记得把路径上经过的点颜色修改一下……因为这里挂了调了好久(

    Code

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #define N (100009)
      6 #define MOD (1000000007)
      7 using namespace std;
      8 
      9 struct Edge{int to,next;}edge[N];
     10 int T,n,c,q,x,a,l,opt,ans,dfs_num,D,MaxDep;
     11 int DFN[N],Depth[N],Size[N];
     12 int head[N],num_edge;
     13 
     14 struct Node
     15 {
     16     int Max[2],Min[2],d[2],ls,rs,col,cov;
     17     bool operator < (const Node &a) const {return d[D]<a.d[D];}
     18 }p[N],Q;
     19 
     20 struct KDT
     21 {
     22     Node T[N];
     23     void Pushup(int now)
     24     {
     25         int ls=T[now].ls,rs=T[now].rs;
     26         for (int i=0; i<=1; ++i)
     27         {
     28             T[now].Max[i]=T[now].Min[i]=T[now].d[i];
     29             if (ls)
     30             {
     31                 T[now].Max[i]=max(T[now].Max[i],T[ls].Max[i]);
     32                 T[now].Min[i]=min(T[now].Min[i],T[ls].Min[i]);
     33             }
     34             if (rs)
     35             {
     36                 T[now].Max[i]=max(T[now].Max[i],T[rs].Max[i]);
     37                 T[now].Min[i]=min(T[now].Min[i],T[rs].Min[i]);
     38             }
     39         }
     40     }
     41     void Pushdown(int now)
     42     {
     43         if (T[now].cov!=-1)
     44         {
     45             int ls=T[now].ls,rs=T[now].rs;
     46             T[ls].cov=T[ls].col=T[now].cov;
     47             T[rs].cov=T[rs].col=T[now].cov;
     48             T[now].cov=-1;
     49         }
     50     }
     51     int Build(int opt,int l,int r)
     52     {
     53         if (l>r) return 0;
     54         int mid=(l+r)>>1;
     55         D=opt; nth_element(p+l,p+mid,p+r+1);
     56         T[mid]=p[mid];
     57         T[mid].ls=Build(opt^1,l,mid-1);
     58         T[mid].rs=Build(opt^1,mid+1,r);
     59         Pushup(mid); return mid;
     60     }
     61     int Query(int now)
     62     {
     63         if (Q.d[0]<T[now].Min[0] || Q.d[0]>T[now].Max[0]) return 0;
     64         if (Q.d[1]<T[now].Min[1] || Q.d[1]>T[now].Max[1]) return 0;
     65         if (Q.d[0]==T[now].d[0] && Q.d[1]==T[now].d[1]) return T[now].col;
     66         Pushdown(now); return Query(T[now].ls)+Query(T[now].rs);
     67     }
     68     void Update(int now,int k)
     69     {
     70         if (Q.Min[0]>T[now].Max[0] || Q.Max[0]<T[now].Min[0] || Q.Min[1]>T[now].Max[1] || Q.Max[1]<T[now].Min[1]) return;
     71         if (Q.Min[0]<=T[now].Min[0] && Q.Max[0]>=T[now].Max[0] && Q.Min[1]<=T[now].Min[1] && Q.Max[1]>=T[now].Max[1])
     72         {
     73             T[now].col=k; T[now].cov=k;
     74             return;
     75         }
     76         Pushdown(now);
     77         if (T[now].d[0]>=Q.Min[0] && T[now].d[0]<=Q.Max[0] && T[now].d[1]>=Q.Min[1] && T[now].d[1]<=Q.Max[1])
     78             T[now].col=k;
     79         Update(T[now].ls,k); Update(T[now].rs,k);
     80     }
     81 }KDT;
     82 
     83 inline int read()
     84 {
     85     int x=0; char c=getchar();
     86     while (c<'0' || c>'9') c=getchar();
     87     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
     88     return x;
     89 }
     90 
     91 void add(int u,int v)
     92 {
     93     edge[++num_edge].to=v;
     94     edge[num_edge].next=head[u];
     95     head[u]=num_edge;
     96 }
     97 
     98 void DFS(int x)
     99 {
    100     Size[x]=1; DFN[x]=++dfs_num;
    101     for (int i=head[x]; i; i=edge[i].next)
    102     {
    103         Depth[edge[i].to]=Depth[x]+1;
    104         DFS(edge[i].to);
    105         Size[x]+=Size[edge[i].to];
    106     }
    107     MaxDep=max(MaxDep,Depth[x]);
    108 }
    109 
    110 int main()
    111 {
    112     T=read();
    113     while (T--)
    114     {
    115         memset(head,0,sizeof(head));
    116         memset(Depth,0,sizeof(Depth));
    117         num_edge=dfs_num=MaxDep=ans=0;
    118         n=read(); c=read(); q=read();
    119         for (int i=1; i<=n; ++i)
    120             p[i].col=1, p[i].cov=-1;
    121         for (int i=2; i<=n; ++i)
    122             x=read(), add(x,i);
    123         DFS(1);
    124         for (int i=1; i<=n; ++i)
    125             p[i].d[0]=DFN[i], p[i].d[1]=Depth[i];
    126         int Root=KDT.Build(0,1,n);
    127         for (int i=1; i<=q; ++i)
    128         {
    129             a=read(); l=read(); opt=read();
    130             if (opt==0)
    131             {
    132                 Q.d[0]=DFN[a]; Q.d[1]=Depth[a];
    133                 (ans+=1ll*i*KDT.Query(Root)%MOD)%=MOD;
    134             }
    135             else
    136             {
    137                 Q.Min[0]=DFN[a]; Q.Max[0]=DFN[a]+Size[a]-1;
    138                 Q.Min[1]=Depth[a]; Q.Max[1]=min(MaxDep,Depth[a]+l);
    139                 KDT.Update(Root,opt);
    140             }
    141         }
    142         printf("%d
    ",ans);
    143     }
    144 }
  • 相关阅读:
    利用scanf函数修改内存中任意位置内容
    TSql
    完整性约束及其违约处理
    实现关机、重启、注销
    建立索引的原则
    我只想安静的大便
    格式化GridView特定的值
    SELECT语句执行顺序解析
    CPU对存储器的读写
    Linux常用97条命令
  • 原文地址:https://www.cnblogs.com/refun/p/10226010.html
Copyright © 2011-2022 走看看