您的位置:首页 > 其它

bzoj4154

2015-06-30 10:14 120 查看
一开始读错题,各种不会做,后来发现染色只是染孩子……

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

染色如果没有距离限制,它就是个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=1000000007;
type node=record
l,c,a:longint;
end;
way=record
po,next:longint;
end;

var  a:array[0..100010] of node;
e:array[0..100010] of way;
v:array[0..100010*4] of boolean;
ans,fa,d,ld,rd,p,q,tq:array[0..100010] of longint;
tag,st:array[0..100010*4] 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<>0 do
begin
y:=e[i].po;
d[y]:=d[x]+1;
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 1];
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]<>0 then
begin
deal(i*2,tag[i]);
deal(i*2+1,tag[i]);
tag[i]:=0;
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 1;
push(i);
if x<=m then work(i*2,l,m,x,y,z);
if y>m then work(i*2+1,m+1,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 1;
push(i);
if x<=m then exit(ask(i*2,l,m,x))
else exit(ask(i*2+1,m+1,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 1;
t:=0;
tot:=0;
h:=0;
for i:=l to r do
begin
if (q[i]<=m) and (a[q[i]].c<>0) or (q[i]>m) and (a[q[i]].c=0) then
begin
inc(t);
tq[t]:=q[i];
end;
if q[i]<=m then inc(h);
end;
for i:=1 to t do
begin
x:=tq[i];
if a[x].c=0 then
begin
f1:=ask(1,1,n,ld[a[x].a]);
if f1>0 then ans[x]:=a[f1].c;
end
else work(1,1,n,ld[a[x].a],rd[a[x].a],x);
end;
for i:=1 to tot do
begin
tag[st[i]]:=0;
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-1);
cdq(f1,r);
end;

begin
readln(tt);
while tt>0 do
begin
dec(tt);
fillchar(p,sizeof(p),0);
readln(n,m,k);
len:=0;
for i:=2 to n do
begin
read(fa[i]);
add(fa[i],i);
end;
t:=0;
dfs(1);
for i:=1 to k do
begin
readln(a[i].a,a[i].l,a[i].c);
if a[i].c<>0 then
begin
a[i].l:=a[i].l+d[a[i].a];
ans[i]:=0;
end
else begin
a[i].l:=d[a[i].a];
ans[i]:=1;
end;
q[i]:=i;
end;
sort(1,k);
cdq(1,k);
s:=0;
for i:=1 to k do
s:=(s+int64(ans[i])*int64(i)) mod mo;
writeln(s);
end;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: