P1486 [NOI2004]郁闷的出纳员

\(\texttt{NOI2004}\) 老贼丧天良!!!!

先说一下思路。首先我们记录一个 \(money\) 代表我们现在的工资起伏状况 (很显然是一个全局的标记)。我们要知道,前面的员工的工资被减了,后面的是不会减的,所以我们插入的时候插入一个 \(val-money\),提取的时候用 \(tree_x+money\) 就可以了。

写的是 \(\texttt{FHQTreap}\),所以删除的时候直接把小于底线的子树抛弃。

您需要注意的是 :

  • if (tree[now]+money)<val then 您是否写成了 <=
  • Insert 中的 Split(root,x,y,val+money); 您是否写成了 Split(root,x,y,val); (如果是,你可能会看到 \(7\) 的左右儿子都是 \(6\) 的神奇情况)
  • Delete 中的 Split(root,x,y,val); 您是否写成了 Split(root,x,y,val-1);
  • if k>=border then Insert(k-money); 您是否写成了 if k<border then inc(outsize) else Insert(k-money);,请认真阅读最后一句话。
  • Query 中的 if k<=0 then exit(-1); 加了没有。

(这东西是显然可以 \(\texttt{AYH}\) 优化的,那位说自己跑得飞快的同学要注意了)

// luogu-judger-enable-o2
// FHQ Treap

Uses math;

Const
    total=100010 << 1;
    RP=23333;

var
    size,tree,heap:array[-1..total] of longint;
    son:array[-1..total,-1..2] of longint;
    i,j,m,n,k,root,money,border,outside:longint;
    order:char;

procedure Add(val:longint); begin inc(n); size[n]:=1; tree[n]:=val; heap[n]:=random(RP); end;

procedure Split(now:longint;var a,b:longint;val:longint);
begin
    if now=0 then begin a:=0; b:=0; exit; end;
    if (tree[now]+money)<val then
    begin a:=now; Split(son[now,1],son[a,1],b,val); end
    else begin b:=now; Split(son[now,0],a,son[b,0],val); end;
    size[now]:=size[son[now,0]]+size[son[now,1]]+1;
end;

procedure Merge(var now:longint;a,b:longint);
begin
    if (a=0)or(b=0) then begin now:=a+b; exit; end;
    if (heap[a]<heap[b]) then
    begin now:=a; Merge(son[now,1],son[a,1],b); end
    else begin now:=b; Merge(son[now,0],a,son[b,0]); end;
    size[now]:=size[son[now,0]]+size[son[now,1]]+1;
end;

procedure Insert(val:longint);
var x,y,o:longint;
begin
    x:=0; y:=0; Add(val); o:=n;
    Split(root,x,y,val+money); Merge(x,x,o); Merge(root,x,y);
end;

procedure Delete(val:longint);
var x,y:longint;
begin
    x:=0; y:=0; Split(root,x,y,val);
    inc(outside,size[x]); root:=y;
end;

function Query(now,k:longint):longint;
begin
    if k<=0 then exit(-1); Query:=0;
    if size[son[now,0]]+1=k then exit(tree[now]+money);
    if size[son[now,0]]>=k then Query:=Query(son[now,0],k) else
    Query:=Query(son[now,1],k-size[son[now,0]]-1);
end;

begin
    randomize; root:=1; Add(maxlongint div 843); heap[root]:=-maxlongint;
    readln(m,border); money:=0;
    for i:=1 to m do
    begin
        readln(order,k);
        if (order='I') then if k>=border then Insert(k-money); 
        if (order='A') then inc(money,k);
        if (order='S') then begin dec(money,k); Delete(border); end;
        if (order='F') then writeln(Query(root,size[root]-k));
    end;
    writeln(outside);
end.
posted @ 2019-03-26 13:34  _ARFA  阅读(165)  评论(0编辑  收藏  举报