bzoj4154

时间:2021-11-13 07:09:45

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

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

染色如果没有距离限制,它就是个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为关键字排序了,

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

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

然后递归下去处理即可

 const mo=;
type node=record
l,c,a:longint;
end;
way=record
po,next:longint;
end; var a:array[..] of node;
e:array[..] of way;
v:array[..*] of boolean;
ans,fa,d,ld,rd,p,q,tq:array[..] of longint;
tag,st:array[..*] of longint;
tot,k,i,n,m,tt,t,x,y,len:longint;
s:int64; procedure add(x,y:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
p[x]:=len;
end; procedure dfs(x:longint);
var i,y:longint;
begin
inc(t);
ld[x]:=t;
i:=p[x];
while i<> do
begin
y:=e[i].po;
d[y]:=d[x]+;
dfs(y);
i:=e[i].next;
end;
rd[x]:=t;
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; function cmp(i,j:longint):boolean;
begin
if a[i].l=a[j].l then exit(a[i].c>a[j].c);
exit(a[i].l>a[j].l);
end; procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=q[(l+r) shr ];
repeat
while cmp(q[i],x) do inc(i);
while cmp(x,q[j]) do dec(j);
if not(i>j) then
begin
swap(q[i],q[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure deal(i,x:longint);
begin
if (tag[i]<x) then tag[i]:=x;
if not v[i] then
begin
inc(tot);
st[tot]:=i;
v[i]:=true;
end;
end; procedure push(i:longint);
begin
if tag[i]<> then
begin
deal(i*,tag[i]);
deal(i*+,tag[i]);
tag[i]:=;
end;
end; procedure work(i,l,r,x,y,z:longint);
var m:longint;
begin
if (x<=l) and (y>=r) then
deal(i,z)
else begin
m:=(l+r) shr ;
push(i);
if x<=m then work(i*,l,m,x,y,z);
if y>m then work(i*+,m+,r,x,y,z);
end;
end; function ask(i,l,r,x:longint):longint;
var m:longint;
begin
if (l=r) then exit(tag[i])
else begin
m:=(l+r) shr ;
push(i);
if x<=m then exit(ask(i*,l,m,x))
else exit(ask(i*+,m+,r,x));
end;
end; procedure cdq(l,r:longint);
var i,t,x,f1,f2,h:longint;
begin
if l=r then exit;
m:=(l+r) shr ;
t:=;
tot:=;
h:=;
for i:=l to r do
begin
if (q[i]<=m) and (a[q[i]].c<>) or (q[i]>m) and (a[q[i]].c=) then
begin
inc(t);
tq[t]:=q[i];
end;
if q[i]<=m then inc(h);
end;
for i:= to t do
begin
x:=tq[i];
if a[x].c= then
begin
f1:=ask(,,n,ld[a[x].a]);
if f1> then ans[x]:=a[f1].c;
end
else work(,,n,ld[a[x].a],rd[a[x].a],x);
end;
for i:= to tot do
begin
tag[st[i]]:=;
v[st[i]]:=false;
end;
f1:=l;
f2:=l+h;
for i:=l to r do
if q[i]<=m then
begin
tq[f1]:=q[i];
inc(f1);
end
else begin
tq[f2]:=q[i];
inc(f2);
end;
for i:=l to r do
q[i]:=tq[i];
cdq(l,f1-);
cdq(f1,r);
end; begin
readln(tt);
while tt> do
begin
dec(tt);
fillchar(p,sizeof(p),);
readln(n,m,k);
len:=;
for i:= to n do
begin
read(fa[i]);
add(fa[i],i);
end;
t:=;
dfs();
for i:= to k do
begin
readln(a[i].a,a[i].l,a[i].c);
if a[i].c<> then
begin
a[i].l:=a[i].l+d[a[i].a];
ans[i]:=;
end
else begin
a[i].l:=d[a[i].a];
ans[i]:=;
end;
q[i]:=i;
end;
sort(,k);
cdq(,k);
s:=;
for i:= to k do
s:=(s+int64(ans[i])*int64(i)) mod mo;
writeln(s);
end;
end.