题意:给出一个n个节点的有根树(编号为0到n-1,根节点为0)。
一个点的深度定义为这个节点到根的距离+1。
q个询问,每个询问给出区间[l,r]和z,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和
好题...orz
并不会写题解...
const
mo=201314;
type
rec=record
l,r:longint;
sum,lazy:int64;
end;
type
rec2=record
p,num,z,op:longint;
end;
var
n,m,l,ll,rr,z :longint;
i :longint;
now,tot,x,y :longint;
q :array[0..100010] of rec2;
last,size,top,d :array[0..50010] of longint;
father,max_son :array[0..50010] of longint;
num :array[0..50010] of longint;
vis :array[0..50010] of boolean;
t :array[0..200010] of rec;
pre,other :array[0..100010] of longint;
ans :array[0..50010] of int64;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure sort(l,r:longint);
var
i,j,x:longint;
y:rec2;
begin
i:=l; j:=r; x:=q[(l+r)>>1].p;
while (i<=j) do
begin
while q[i].p<x do inc(i);
while q[j].p>x do dec(j);
if (i<=j) then
begin
y:=q[i]; q[i]:=q[j]; q[j]:=y;
inc(i); dec(j);
end;
end;
if i<r then sort(i,r);
if j>l then sort(l,j);
end;
procedure dfs(x:longint);
var
p,q:longint;
begin
size[x]:=1;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] then
begin
vis[p]:=true;
father[p]:=x;
dfs(p);
inc(size[x],size[p]);
if size[max_son[x]]<size[p] then max_son[x]:=p;
end;
q:=pre[q];
end;
end;
procedure make(x,t,depth:longint);
var
p,q:longint;
begin
inc(tot);
num[x]:=tot;
top[x]:=t;
d[x]:=depth;
vis[x]:=true;
if max_son[x]<>0 then
begin
vis[max_son[x]]:=true;
make(max_son[x],t,depth);
end;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] and (p<>max_son[x]) then
begin
vis[p]:=true;
make(p,p,depth+1);
end;
q:=pre[q];
end;
end;
procedure build(x,l,r:longint);
var
mid:longint;
begin
t[x].l:=l; t[x].r:=r;
if l=r then
begin
t[x].sum:=1;exit;
end;
mid:=(l+r)>>1;
build(2*x,l,mid); build(2*x+1,mid+1,r);
t[x].sum:=t[x*2].sum+t[2*x+1].sum;
end;
procedure update(x:longint);
begin
inc(t[x].sum,t[x].lazy*int64(t[x].r-t[x].l+1));
if t[x].l=t[x].r then
begin
t[x].lazy:=0;exit;
end;
inc(t[2*x].lazy,t[x].lazy);
inc(t[2*x+1].lazy,t[x].lazy);
t[x].lazy:=0;
end;
procedure change(x,l,r,z:longint);
var
mid:longint;
begin
if (t[x].l=l) and (t[x].r=r) then
begin
inc(t[x].lazy,z);exit;
end;
if t[x].lazy<>0 then update(x);
mid:=(t[x].l+t[x].r)>>1;
if r<=mid then change(2*x,l,r,z) else
if l>mid then change(2*x+1,l,r,z) else
begin
change(2*x,l,mid,z);
change(2*x+1,mid+1,r,z);
end;
t[x].sum:=t[2*x].sum+t[2*x+1].sum
+t[2*x].lazy*int64(t[2*x].r-t[2*x].l+1)
+t[2*x+1].lazy*int64(t[2*x+1].r-t[2*x+1].l+1);
end;
function get_sum(x,l,r:longint):int64;
var
mid:longint;
begin
if (t[x].lazy<>0) then update(x);
if (t[x].l=l) and (t[x].r=r) then exit(t[x].sum);
mid:=(t[x].l+t[x].r)>>1;
if r<=mid then exit(get_sum(2*x,l,r)) else
if l>mid then exit(get_sum(2*x+1,l,r)) else
exit(get_sum(2*x,l,mid)+get_sum(2*x+1,mid+1,r));
end;
procedure change1(x,y:longint);
begin
while (d[x]<d[y]) do
begin
change(1,num[top[y]],num[y],1);
y:=father[top[y]];
end;
while (top[x]<>top[y]) do
begin
change(1,num[top[y]],num[y],1);
change(1,num[top[x]],num[x],1);
y:=father[top[y]];
x:=father[top[x]];
end;
if num[x]<num[y] then change(1,num[x],num[y],1)
else change(1,num[y],num[x],1);
end;
function query(x,y:longint):int64;
var
ans:int64;
begin
ans:=0;
while (d[x]<d[y]) do
begin
inc(ans,get_sum(1,num[top[y]],num[y]));
y:=father[top[y]];
end;
while (top[x]<>top[y]) do
begin
inc(ans,get_sum(1,num[top[y]],num[y]));
inc(ans,get_sum(1,num[top[x]],num[x]));
y:=father[top[y]];
x:=father[top[x]];
end;
if num[x]<num[y] then inc(ans,get_sum(1,num[x],num[y]))
else inc(ans,get_sum(1,num[y],num[x]));
ans:=ans mod mo;
exit(ans);
end;
begin
read(n,m);
for i:=1 to n-1 do
begin
read(x);
inc(x);
connect(x,i+1);
connect(i+1,x);
end;
vis[1]:=true; dfs(1);
fillchar(vis,sizeof(vis),false);
vis[1]:=true; make(1,1,1);
build(1,1,n);
for i:=1 to m do
begin
read(ll,rr,z);
inc(ll); inc(rr); inc(z);
q[2*i].p:=ll-1; q[2*i].num:=i; q[2*i].op:=-1; q[i*2].z:=z;
q[2*i-1].p:=rr; q[2*i-1].num:=i; q[2*i-1].op:=1; q[i*2-1].z:=z;
end;
sort(1,2*m);
now:=1;
for i:=1 to m*2 do
begin
while (now<=n) and (now<=q[i].p) do
begin
change1(1,now);
inc(now);
end;
ans[q[i].num]:=(ans[q[i].num]+q[i].op*query(1,q[i].z)+mo) mod mo;
end;
for i:=1 to m do writeln(ans[i]);
end.
——by Eirlys