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\n",ans);
143     }
144 }
posted @ 2019-01-05 20:27  Refun  阅读(162)  评论(0编辑  收藏  举报