Splay(dispatching)

原题:APIO 2012 派遣

方法:splay 启发式合并

program dispatching;
const maxn=100000+100;
type
    link=^node;node=record x:longint; next:link;end;
var
    l,r,s,w,f,fa:array[1..maxn]of longint;
    ge:array[1..maxn]of link;
procedure push(var x:link;const t:longint);inline;var p:link;
begin
    new(p);p^.x:=t;p^.next:=x;x:=p;
end;
procedure update(const x:longint);inline;
begin
    s[x]:=s[l[x]]+s[r[x]]+1;
    f[x]:=f[l[x]]+f[r[x]]+w[x];
end;
procedure left(var i:longint);var j:longint;
begin
    j:=r[i];r[i]:=l[j];l[j]:=i;
    s[j]:=s[i];f[j]:=f[i];update(j);i:=j;
end;
procedure right(var i:longint);var j:longint;
begin
    j:=l[i];l[i]:=r[j];r[j]:=i;
    s[j]:=s[i];f[j]:=f[i];update(j);i:=j;
end;
procedure insert(var i:longint;const j:longint);
begin
    if i=0 then begin i:=j; exit; end;
    if w[j]<=w[i] then begin
	insert(l[i],j);right(i);
    end else begin
	insert(r[i],j);left(i);
    end;
end;
function union(x,y:longint):longint;
var ll,rr:longint;
begin
    if (x=0)or(y=0) then exit(x+y);
    if x=y then exit(x);
    ll:=l[y];l[y]:=0;
    rr:=r[y];r[y]:=0;
    s[y]:=0; insert(x,y);
    l[y]:=union(l[x],ll);
    r[y]:=union(r[x],rr);
    update(x);exit(x);
end;
while find(x:longint):longint;
begin
    while x<>0 do begin
	if s[l[x]]+1=k then exit(X);
	if s[l[x]]<k then x:=l[x] else
	begin dec(k,s[l[x]]); x:=r[x]; end;
    end;
end;

var n,i,h,t,ans:longint; p:link;
procedure getans(const x:longint);inline;
begin if x>ans then ans:=x;end;
begin
    readln(n);
    for i:=1 to n do begin 
	readln(fa[i],w[i],l[i]); 
	push(ge[fa[i]],i);
    end;
    for i:=1 to n do begin s[i]:=1;tt[i]:=i;end;
    while h<t do begin 
	inc(h); p:=ge[q[h]]; 
	while p<>nil do begin 
	    inc(t);q[t]:=p^.x;p:=p^.next;
	    tt[q[h]]:=union(ls[x]);
	end;
    end;
    for i:=n downto 1 do begin
	p:=ge[q[i]];while p<>nil do begin
	    tt[q[i]]:=union(tt[p^.x]);
	x:=x^.next;end
	getans(l[q[i]]*find(tt[q[i]]));
    end;
end;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值