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.
- BZOJ 1588 BZOJ 1503 平衡数splay
- BZOJ 3223 文艺平衡树 (splay)
- 【Splay】bzoj 3223 文艺平衡树
- BZOJ 3223 文艺平衡树 【Splay】
- 【splay】BZOJ 3224 普通平衡树
- 【splay】BZOJ 3223 文艺平衡树
- bzoj 3223 文艺平衡树 Splay
- 【BZOJ 3224】普通平衡树-Splay
- 【BZOJ】Tyvj 1729 文艺平衡树 Splay
- BZOJ 1588 Splay 入门
- bzoj 1588 splay 模板
- BZOJ 1588 splay
- BZOJ 1588 Splay树
- BZOJ 1503 splay
- bzoj 1588 营业额统计 splay
- BZOJ 1588 营业额统计 Splay
- BZOJ 1588 营业额统计 Splay
- BZOJ 1588 营业额统计 Splay
- scanf能不能与gets一起用
- 虚函数和纯虚函数的区别
- linux vi替换字符串
- this指针常用用法(C++ )
- Linux VPN服务器搭建
- BZOJ 1588 BZOJ 1503 平衡数splay
- Linux下如何搭建VPN服务器
- 向Web开发人员推荐12款优秀的 Twitter Bootstrap 组件和工具
- 三月其他零散知识(技术)
- 计算机是怎么启动起来的?值得一看
- 【Linux】Ubuntu 12.04和Windows 7双系统安装图解
- ServiceDescriptionImporter 类在 vs2010 无法引用的解决方法
- 三月其他零散知识(非技术)
- MFC中消息响应函数定义及消息映射宏定义参考