# [BZOJ3011][Usaco2012 Dec]Running Away From the Barn

**没仔细看题数据是longlong啊。。

uses math;
type re=record
a,b,c,num:int64;
end;
type ree=record
h,t,x:longint;
end;
var
i,j:longint;
now,m,n,c,d,k,l,o,ans,x,tmp:int64;
a,dis:array[1..500000]of re;
f:array[1..500000]of boolean;
p:array[0..5000000]of ree;
procedure arr(x,y,z:int64);
begin
inc(l);
a[l].b:=y;
a[l].c:=z;
end;
function dfs(x,y:int64):int64;
var u,v:longint;
begin
f[x]:=false; dis[x].a:=y; dis[x].b:=x;
inc(now); dis[x].num:=now;
while u<>0 do
begin
v:=a[u].b;
if f[v] then dfs:=max(dfs,dfs(v,y+a[u].c));
u:=a[u].a;
end;
dis[x].c:=dfs;
end;
procedure swap(var x,y:re);
var tmp:re;
begin
tmp:=x; x:=y; y:=tmp;
end;
procedure qsort(h,t:int64);
var i,j,mid:int64;
begin
i:=h; j:=t; mid:=dis[(h+t) div 2].a;
repeat
while dis[i].a<mid do inc(i);
while dis[j].a>mid do dec(j);
if i<=j then
begin
swap(dis[i],dis[j]);
inc(i); dec(j);
end;
until i>j;
if i<t then qsort(i,t);
if h<j then qsort(h,j);
end;
procedure build(x,h,t:int64);
var mid:int64;
begin
p[x].h:=x*2; p[x].t:=x*2+1; now:=max(now,x*2+1);
if h=t then exit;
mid:=(h+t) div 2;
build(x*2,h,mid); build(x*2+1,mid+1,t);
end;
function find(x:int64):int64;
var h,t,mid:int64;
begin
h:=1; t:=n;
while h<t do
begin
mid:=(h+t) div 2+1;
if dis[mid].a<=x then h:=mid else t:=mid-1;
end;
exit(h);
end;
procedure insert(pre,x,h,t:int64);
var tmp,mid:longint;
begin
inc(now); p[now]:=p[pre]; inc(p[now].x); tmp:=now;
if h=t then exit;
mid:=(h+t) div 2;
if (x<=mid) then
begin
insert(p[now].h,x,h,mid);
p[tmp].h:=tmp+1;
end else
begin
insert(p[now].t,x,mid+1,t);
p[tmp].t:=tmp+1;
end;
end;
function query(x,h1,t1,h,t:int64):int64;
var mid:int64;
begin
if (h>t1) or (t<h1) then exit(0);
if (h<=h1) and (t1<=t) then exit(p[x].x);
mid:=(h1+t1) div 2;
exit(query(p[x].h,h1,mid,h,t)+query(p[x].t,mid+1,t1,h,t));
end;
begin
for i:=1 to n-1 do
begin
end;
dfs(1,0);
qsort(1,n); o:=0;
for i:=1 to n do
begin
if (i=1) or (dis[i].a<>dis[i-1].a) then
inc(o);
num[i]:=o;
end;
now:=0; build(1,1,n);
fa[0]:=1;
for i:=1 to n do
begin
if (i<>1) and (num[i]=num[i-1]) then
begin
tmp:=now;
insert(fa[num[i]],dis[i].num,1,n);
fa[num[i]]:=tmp+1;
end
else
begin
fa[num[i]]:=now+1;
insert(fa[num[i]-1],dis[i].num,1,n);
end;
end;
for i:=1 to n do
begin
x:=find(dis[i].a+k);
ans:=query(fa[num[x]],1,n,dis[i].num,dis[i].c);
q[dis[i].b]:=ans;
end;
for i:=1 to n do writeln(q[i]);
end.

方法3：左偏树

type re=record
a,b,c:int64;
end;
var
i,j:longint;
m,n,ans,l,c,d:int64;
k:int64;
f:array[1..1000000]of boolean;
a:array[1..1000000]of re;
procedure arr(x,y,z:int64);
begin
inc(l);
a[l].b:=y;
a[l].c:=z;
end;
function getfa(x:int64):int64;
begin
while (fa[x]<>0) do x:=fa[x];
exit(x);
end;
procedure swap(var x,y:int64);
var tmp:int64;
begin
tmp:=x; x:=y; y:=tmp;
end;
function merge(x,y:int64):int64;
var tmp:int64;
begin
if (x=0) or (y=0) then exit(x+y);
if (dis[x]<dis[y]) then swap(x,y);
right1[x]:=merge(right1[x],y);
fa[right1[x]]:=x;
if (ll[left1[x]]<ll[right1[x]]) then swap(left1[x],right1[x]);
ll[x]:=ll[right1[x]]+1; cnt[x]:=cnt[left1[x]]+cnt[right1[x]]+1;
exit(x);
end;
function delete(x:int64):int64;
var tmp:int64;
begin
fa[left1[x]]:=0; fa[right1[x]]:=0;
if left1[x]<>0 then tmp:=left1[x] else tmp:=right1[x];
merge(left1[x],right1[x]);
exit(getfa(tmp));
end;
procedure dfs(x,y:int64);
var u,v,c,d,goal,ans,z:int64;
begin
ans:=0;  f[x]:=false; dis[x]:=y;
while u<>0 do
begin
v:=a[u].b;
if f[v] then
begin
dfs(v,y+a[u].c);
c:=getfa(v); goal:=y+k;
while (c<>0)  and (dis[c]>goal) do
begin
c:=delete(c);
end;
if c<>0 then
begin
ans:=ans+cnt[c];
z:=getfa(x);
merge(z,c);
end;
end;
u:=a[u].a;
end;
if k>=0 then vv[x]:=ans+1 else vv[x]:=ans;
end;
begin
if k<0 then writeln('111');
for i:=1 to n-1 do
begin
end.