bzoj4154

一开始读错题,各种不会做,后来发现染色只是染孩子……

那不就简单了吗……注意这题是允许离线的

染色如果没有距离限制,它就是个dfs序

距离限制怎么做呢?我们考虑扩展一维变成二维的问题,将每个点变为二维平面上的点(x,y),y=d[x]表示x的深度

染色a,距离限制l实际上就是对x∈[l,r],y<=d[a]+l的二维点染色([l,r]表示dfs序对应的区间)

这是一个非常经典的思路,我们可以扩展一维方便表示限制

注意染色的贡献是独立的,考虑离线的cdq分治,对于所有操作,我们把l变成d[a]+l;

然后以l为关键字降序排序,然后对时间线分治,设cdq(l,r)表示解决的第[l,r]的所有操作

考虑时间线[l,m]的染色操作对[m+1,r]的查询操作的影响,我们已经按l为关键字排序了,

对询问点产生影响的一定是区间包含这个点的最后一次操作,因此我们维护以时间为关键字的线段树

这样就是维护最大值,区间覆盖,单点查询,用线段树即可

然后递归下去处理即可

  1 const mo=1000000007;
  2 type node=record
  3        l,c,a:longint;
  4      end;
  5      way=record
  6        po,next:longint;
  7      end;
  8
  9 var  a:array[0..100010] of node;
 10      e:array[0..100010] of way;
 11      v:array[0..100010*4] of boolean;
 12      ans,fa,d,ld,rd,p,q,tq:array[0..100010] of longint;
 13      tag,st:array[0..100010*4] of longint;
 14      tot,k,i,n,m,tt,t,x,y,len:longint;
 15      s:int64;
 16
 17 procedure add(x,y:longint);
 18   begin
 19     inc(len);
 20     e[len].po:=y;
 21     e[len].next:=p[x];
 22     p[x]:=len;
 23   end;
 24
 25 procedure dfs(x:longint);
 26   var i,y:longint;
 27   begin
 28     inc(t);
 29     ld[x]:=t;
 30     i:=p[x];
 31     while i<>0 do
 32     begin
 33       y:=e[i].po;
 34       d[y]:=d[x]+1;
 35       dfs(y);
 36       i:=e[i].next;
 37     end;
 38     rd[x]:=t;
 39   end;
 40
 41 procedure swap(var a,b:longint);
 42   var c:longint;
 43   begin
 44     c:=a;
 45     a:=b;
 46     b:=c;
 47   end;
 48
 49 function cmp(i,j:longint):boolean;
 50   begin
 51     if a[i].l=a[j].l then exit(a[i].c>a[j].c);
 52     exit(a[i].l>a[j].l);
 53   end;
 54
 55 procedure sort(l,r:longint);
 56   var i,j,x:longint;
 57   begin
 58     i:=l;
 59     j:=r;
 60     x:=q[(l+r) shr 1];
 61     repeat
 62       while cmp(q[i],x) do inc(i);
 63       while cmp(x,q[j]) do dec(j);
 64       if not(i>j) then
 65       begin
 66         swap(q[i],q[j]);
 67         inc(i);
 68         dec(j);
 69       end;
 70     until i>j;
 71     if l<j then sort(l,j);
 72     if i<r then sort(i,r);
 73   end;
 74
 75 procedure deal(i,x:longint);
 76   begin
 77     if (tag[i]<x) then tag[i]:=x;
 78     if not v[i] then
 79     begin
 80       inc(tot);
 81       st[tot]:=i;
 82       v[i]:=true;
 83     end;
 84   end;
 85
 86 procedure push(i:longint);
 87   begin
 88     if tag[i]<>0 then
 89     begin
 90       deal(i*2,tag[i]);
 91       deal(i*2+1,tag[i]);
 92       tag[i]:=0;
 93     end;
 94   end;
 95
 96 procedure work(i,l,r,x,y,z:longint);
 97   var m:longint;
 98   begin
 99     if (x<=l) and (y>=r) then
100       deal(i,z)
101     else begin
102       m:=(l+r) shr 1;
103       push(i);
104       if x<=m then work(i*2,l,m,x,y,z);
105       if y>m then work(i*2+1,m+1,r,x,y,z);
106     end;
107   end;
108
109 function ask(i,l,r,x:longint):longint;
110   var m:longint;
111   begin
112     if (l=r) then exit(tag[i])
113     else begin
114       m:=(l+r) shr 1;
115       push(i);
116       if x<=m then exit(ask(i*2,l,m,x))
117       else exit(ask(i*2+1,m+1,r,x));
118     end;
119   end;
120
121 procedure cdq(l,r:longint);
122   var i,t,x,f1,f2,h:longint;
123   begin
124     if l=r then exit;
125     m:=(l+r) shr 1;
126     t:=0;
127     tot:=0;
128     h:=0;
129     for i:=l to r do
130     begin
131       if (q[i]<=m) and (a[q[i]].c<>0) or (q[i]>m) and (a[q[i]].c=0) then
132       begin
133         inc(t);
134         tq[t]:=q[i];
135       end;
136       if q[i]<=m then inc(h);
137     end;
138     for i:=1 to t do
139     begin
140       x:=tq[i];
141       if a[x].c=0 then
142       begin
143         f1:=ask(1,1,n,ld[a[x].a]);
144         if f1>0 then ans[x]:=a[f1].c;
145       end
146       else work(1,1,n,ld[a[x].a],rd[a[x].a],x);
147     end;
148     for i:=1 to tot do
149     begin
150       tag[st[i]]:=0;
151       v[st[i]]:=false;
152     end;
153     f1:=l;
154     f2:=l+h;
155     for i:=l to r do
156       if q[i]<=m then
157       begin
158         tq[f1]:=q[i];
159         inc(f1);
160       end
161       else begin
162         tq[f2]:=q[i];
163         inc(f2);
164       end;
165     for i:=l to r do
166       q[i]:=tq[i];
167     cdq(l,f1-1);
168     cdq(f1,r);
169   end;
170
171 begin
172   readln(tt);
173   while tt>0 do
174   begin
175     dec(tt);
176     fillchar(p,sizeof(p),0);
177     readln(n,m,k);
178     len:=0;
179     for i:=2 to n do
180     begin
181       read(fa[i]);
182       add(fa[i],i);
183     end;
184     t:=0;
185     dfs(1);
186     for i:=1 to k do
187     begin
188       readln(a[i].a,a[i].l,a[i].c);
189       if a[i].c<>0 then
190       begin
191         a[i].l:=a[i].l+d[a[i].a];
192         ans[i]:=0;
193       end
194       else begin
195         a[i].l:=d[a[i].a];
196         ans[i]:=1;
197       end;
198       q[i]:=i;
199     end;
200       sort(1,k);
201     cdq(1,k);
202     s:=0;
203     for i:=1 to k do
204       s:=(s+int64(ans[i])*int64(i)) mod mo;
205     writeln(s);
206   end;
207 end.

时间: 2024-11-09 09:56:18

bzoj4154的相关文章

【kd-tree】bzoj4154 [Ipsc2015]Generating Synergy

区间修改的kd-tree,打标记,下传. 每次询问的时候,从询问点向上找到根,然后依次下传下来,再回答询问. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 100001 #define KD 2 int n,root,m,q,qp[2][KD],fa[N],val,delta[N]; bool dn; struct Node { int ch[2

【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

[BZOJ4154][Ipsc2015]Generating Synergy 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

BZOJ4154 : [Ipsc2015]Generating Synergy

求出dfs序和每个点的深度 将第i个点看成二维点(st[i],d[i]) 则修改操作等价于将横坐标在[st[x],en[x]]内,纵坐标在[d[x],d[x]+y]范围内的点的颜色都修改为c 用支持标记下放的k-d树维护即可,时间复杂度$O(n\log n+q\sqrt{n})$. #include<cstdio> #include<algorithm> #define N 100010 int T,n,c,m,x,y,i,g[N],nxt[N],st[N],en[N],dfn,d

【bzoj4154】[Ipsc2015]Generating Synergy KD-tree

题目描述 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 输入 第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数 接下来一行n-1个数描述2..n的父节点 接下来q行每行三个数a,l,c 若c为0,表示询问a的颜色 否则将距离a不超过l的a的子节点染成c 输出 设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+..

BZOJ4154——IPSC2015 Generating Synergy

题意:AC通道 题解: 这题有个十分巧妙的解法. 因为有子树修改,而又不是整棵子树的修改,直接上dfs序是不行的. 考虑它每次修改的只有子节点,而且有距离限制,我们想到这是与点的深度有关的问题. 于是我们把树上的点抽象到二维平面上,横坐标为其dfs序,纵坐标为其深度,这样每次的修改就对应一个区域的染色操作,这东西用kdtree可以随便搞,弄个lazytag就可以了. 一堆调试用的代码,所以看起来很长. #include <bits/stdc++.h> //#include <conio.