BZOJ 1588 BZOJ 1503 平衡数splay

来源:互联网 发布:windows 登陆服务器 编辑:程序博客网 时间:2024/05/22 09:38

虽然去年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;  endelse  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;  endelse  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;  endelse 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;  endelse 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;    endelse   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  begininc(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.