虽然去年11月就会splay了..
不过前天实战一个splay好像写跪了?
还有6天就省选了..就复习了一下..
关于BZOJ1588
是一个学平衡树都会写的一题...
插入一个.求前序,求后继,找一个最小的..
看了discuss发现貌似有几个点最后会少一行=- =
弄成while循环就好啦 少掉的算0..
代码略丑
var
l,r,fa,a:array[0..100000] of longint;
root,ans,n,i,x:longint;
procedure zig(x:longint);
var
y,z:longint;
begin
y:=fa[x];z:=fa[y];
if r[x]<>0 then
begin
l[y]:=r[x];
fa[r[x]]:=y;
end
else
l[y]:=0;
fa[y]:=x;r[x]:=y;
if root=y then begin root:=x;exit;end;
fa[x]:=z;if l[z]=y then l[z]:=x else r[z]:=x;
end;
procedure zag(x:longint);
var
y,z:longint;
begin
y:=fa[x];z:=fa[y];
if l[x]<>0 then
begin
r[y]:=l[x];
fa[l[x]]:=y;
end
else
r[y]:=0;
fa[y]:=x;l[x]:=y;
if root=y then begin root:=x;exit;end;
fa[x]:=z;if l[z]=y then l[z]:=x else r[z]:=x;
end;
procedure splay(k:longint);
begin
while k<>root do
if (l[fa[k]]=k) then
if (fa[k]=root) then zig(k)
else
if (l[fa[fa[k]]]=fa[k]) then
begin
zig(fa[k]);zig(k);
end
else
begin
zig(k);zag(k);
end
else
if (fa[k]=root) then zag(k)
else
if (r[fa[fa[k]]]=fa[k]) then
begin
zag(fa[k]);zag(k);
end
else
begin
zag(k);zig(k);
end;
root:=k;fa[k]:=0;
end;
procedure add(k:longint);
var
i,j:longint;
begin
i:=root;
if i=0 then
begin
root:=k;
exit;
end;
j:=i;
while i<>0 do
begin
j:=i;
if a[i]<=a[k] then i:=r[i] else i:=l[i];
end;
if a[j]<=a[k] then r[j]:=k else l[j]:=k;
fa[k]:=j;
splay(k);
end;
function find(k:longint):longint;
var
i,ans1,ans2:longint;
begin
i:=l[k];ans1:=-1;
while (r[i]<>0) and (i<>0) do
i:=r[i];
if i<>0 then ans1:=abs(a[i]-a[k]);
i:=r[k];ans2:=-1;
while (l[i]<>0) and (i<>0) do
i:=l[i];
if i<>0 then ans2:=abs(a[i]-a[k]);
if (ans1=-1) and (ans2=-1) then exit(a[k]);
if ans1=-1 then exit(ans2);
if ans2=-1 then exit(ans1);
if ans1<ans2 then exit(ans1) else exit(ans2);
end;
begin
fillchar(l,sizeof(l),0);
fillchar(r,sizeof(r),0);
fillchar(fa,sizeof(fa),0);
readln(n);ans:=0;i:=0;
while not eof do
begin
i:=i+1;
readln(a[i]);
add(i);
x:=find(i);
ans:=ans+x;
end;
if i<n then
while i<>n do
begin
i:=i+1;
a[i]:=0;
add(i);
ans:=ans+find(i);
end;
writeln(ans);
end.
1503不算难..
插入 size 找第K大 删除
说一下lazy标记 一路插入 一路下方标记
增加只要把根节点的lazy加就行了
减少工资就要lazy剪掉,然后还要做一个删除操作...
删除操作是每次从根找最小值..然后判断是否比min小 小就删掉(因为是最小的,删除很方便)
一路找,一路下方标记...直到最小的大于等于min
找第K大 直接找就行了...利用size
注意...一开始工资就比min低的人不算在离开公司的人内......
这个代码更丑了。。速度还奇慢=- = 别人几百ms 我要2000msQAQ
Orz purpleslz大神!!
省选加油!
var
size,a,l,r,fa,lazy:array[0..100100] of longint;
ans,root,i,n,min,x,j,sum:longint;
c:char;
procedure zig(x:longint);
var
y,z:longint;
begin
y:=fa[x];z:=fa[y];
a[y]:=a[y]+lazy[y];a[x]:=a[x]+lazy[y]+lazy[x];inc(lazy[r[y]],lazy[y]);
inc(lazy[l[x]],lazy[x]+lazy[y]);inc(lazy[r[x]],lazy[x]+lazy[y]);
lazy[x]:=0;lazy[y]:=0;size[x]:=size[y];size[y]:=size[r[y]]+size[r[x]]+1;
if r[x]<>0 then
begin
l[y]:=r[x];
fa[r[x]]:=y;
end
else l[y]:=0;
fa[y]:=x;fa[x]:=z;r[x]:=y;
if y=root then begin root:=x;exit;end;
if l[z]=y then l[z]:=x else r[z]:=x;
end;
procedure zag(x:longint);
var
y,z:longint;
begin
y:=fa[x];z:=fa[y];
a[y]:=a[y]+lazy[y];a[x]:=a[x]+lazy[y]+lazy[x];inc(lazy[l[y]],lazy[y]);
inc(lazy[l[x]],lazy[x]+lazy[y]);inc(lazy[r[x]],lazy[x]+lazy[y]);
lazy[x]:=0;lazy[y]:=0;size[x]:=size[y];size[y]:=size[l[y]]+size[l[x]]+1;
if l[x]<>0 then
begin
r[y]:=l[x];
fa[l[x]]:=y;
end
else r[y]:=0;
fa[y]:=x;fa[x]:=z;l[x]:=y;
if y=root then begin root:=x;exit;end;
if l[z]=y then l[z]:=x else r[z]:=x;
end;
procedure splay(k:longint);
begin
while k<>root do
if l[fa[k]]=k then
if fa[k]=root then zig(k)
else
if l[fa[fa[k]]]=fa[k] then
begin
zig(fa[k]);zig(k);
end
else
begin
zig(k);zag(k);
end
else
if fa[k]=root then zag(k)
else
if r[fa[fa[k]]]=fa[k] then
begin
zag(fa[k]);zag(k);
end
else
begin
zag(k);zig(k);
end;
fa[k]:=0;size[0]:=0;l[0]:=0;fa[0]:=0;r[0]:=0;lazy[0]:=0;
end;
procedure add(k:longint);
var
i,j:longint;
begin
i:=root;size[k]:=1;
if root=0 then
begin
root:=k;
exit;
end;
while i<>0 do
begin
j:=i;
size[i]:=size[i]+1;
inc(lazy[l[i]],lazy[i]);
inc(lazy[r[i]],lazy[i]);
a[i]:=a[i]+lazy[i];
lazy[i]:=0;
if a[k]<a[i] then i:=l[i] else i:=r[i];
end;
fa[k]:=j;if a[k]<a[j] then l[j]:=k else r[j]:=k;
splay(k);
end;
procedure del;
var
i,J:longint;
flag:boolean;
begin
flag:=true;
while flag do
begin
i:=root;
if root=0 then exit;
while i<>0 do
begin
j:=i;
inc(lazy[l[i]],lazy[i]);
inc(lazy[r[i]],lazy[i]);
a[i]:=a[i]+lazy[i];
lazy[i]:=0;
size[i]:=size[i]-1;
i:=l[i];
end;
i:=j;
if a[i]<min then
if i<>root then
begin
fa[r[i]]:=fa[i];
l[fa[i]]:=r[i];
ans:=ans+1;
end
else
begin
root:=r[i];
fa[r[i]]:=0;
ans:=ans+1;
end
else
begin
flag:=false;
i:=root;
if root=0 then exit;
while i<>0 do
begin
size[i]:=size[i]+1;
i:=l[i];
end;
end;
end;
end;
function find(x:longint):longint;
var
i,sum:longint;
begin
i:=root;
if root=0 then exit(-1);
if (X<=0) or (root=0) then exit(-1);
sum:=0;
while sum<x do
begin
inc(lazy[l[i]],lazy[i]);
inc(lazy[r[i]],lazy[i]);
a[i]:=a[i]+lazy[i];
lazy[i]:=0;
if (size[l[i]]+1+sum)=x then
begin
splay(i);
exit(a[i]);
end;
if (size[l[i]]+1+sum)<x then
begin
sum:=sum+size[l[i]]+1;
i:=r[i];
continue;
end;
i:=l[i];
end;
writeln('error');
end;
begin
readln(n,min);ans:=0;sum:=0;
for i:=1 to n do
begin
read(c);
readln(x);
if c='I' then if x>=min then begin sum:=sum+1;a[sum]:=x;add(sum);end;
if c='A' then inc(lazy[root],x);
if c='S' then begin dec(lazy[root],x);del;end;
if c='F' then begin writeln(find(size[root]-x+1));end;
end;
writeln(ans);
end.