天天看點

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 }      

轉載于:https://www.cnblogs.com/refun/p/10226010.html