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;


Splay删除子树是一种数据结构和算法中的操作,通常用于自平衡二叉搜索树(如AVL、红黑树或Treap)的变种——Splay Tree中。Splay Tree是一种动态查找树,其特点是每次访问后都会对节点进行旋转操作(splaying),使其最近被访问的节点处于根部。 当要删除一个节点时,在常规的二叉搜索树中,我们需要找到该节点并删除它,然后处理可能由删除引起的不平衡。在Splay Tree中,这个过程有所不同: 1. **查找子树**: 首先,我们在树中寻找指定的子树,这可以通过标准的查找算法实现,同时保持对父节点的更新。 2. **Splay节点**: 找到子树后,我们对包含目标节点的路径上的所有节点执行一系列旋转操作(可能是单旋转或双旋转),直到目标节点到达根部。这个过程确保了频繁访问的路径被高效地访问。 3. **删除目标节点**: 当目标节点处于根部时,删除操作变得相对简单。如果目标节点有两颗子树,则替换为其右孩子的最小值或左孩子的最大值(取决于树的类型)。如果只有一个子树,那么就直接删除。 4. **重新平衡** (可选): 取决于Splay Tree的具体实现,可能会有一个额外的步骤来确保整棵树的平衡,但这不是必须的,因为Splay已经尽可能地减少了不平衡的可能性。 Splay删除子树的时间复杂度通常是O(log n),n是树的大小,因为每个旋转操作最多改变一棵高度为h的树的高度至h+1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值