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.
完结撒花!✿✿ヽ(゚▽゚)ノ✿