算法模板——splay区间反转 1
2015-01-14 23:05
309 查看
实现的功能:将序列区间反转,并维护
详见BZOJ3223
详见BZOJ3223
var i,j,k,l,m,n,head,a1,a2:longint; s1:ansistring; a,b,c,d,fat,lef,rig:array[0..200000] of longint; procedure swap(var x,y:longint);inline; var z:longint; begin z:=x;x:=y;y:=z; end; procedure ext(x:longint);inline; begin if (x=0) then exit; if c[x]=0 then exit; swap(lef[x],rig[x]); c[x]:=0; c[lef[x]]:=1-c[lef[x]]; c[rig[x]]:=1-c[rig[x]]; c[0]:=0; end; procedure rt(x:longint);inline; var f,l:longint; begin if x=0 then exit; ext(x); if lef[x]=0 then exit; ext(lef[x]); f:=x;l:=lef[x]; b[lef[x]]:=b[x]; b[x]:=b[rig[x]]+1+b[rig[l]]; lef[x]:=rig[l]; fat[rig[l]]:=x; rig[l]:=x; fat[l]:=fat[x]; fat[x]:=l; if rig[fat[l]]=x then rig[fat[l]]:=l; if lef[fat[l]]=x then lef[fat[l]]:=l; fat[0]:=0; end; procedure lt(x:longint);inline; var f,r:longint; begin if x=0 then exit; ext(x);if rig[x]=0 then exit; ext(rig[x]); f:=x;r:=rig[x]; b[rig[x]]:=b[x]; b[x]:=1+b[lef[x]]+b[lef[r]]; rig[x]:=lef[r]; fat[lef[r]]:=x; lef[r]:=x; fat[r]:=fat[x]; fat[x]:=r; if rig[fat[r]]=x then rig[fat[r]]:=r; if lef[fat[r]]=x then lef[fat[r]]:=r; fat[0]:=0; end; procedure ins(x,y:longint);inline; begin if a[y]<a[x] then begin if lef[x]=0 then begin lef[x]:=y; fat[y]:=x; end else ins(lef[x],y); end else begin if rig[x]=0 then begin rig[x]:=y; fat[y]:=x; end else ins(rig[x],y); end; b[x]:=1+b[lef[x]]+b[rig[x]]; end; procedure up2(var x:longint);inline; begin if (fat[x]=0) or (x=0) then exit; if lef[fat[x]]=x then begin if lef[fat[fat[x]]]=fat[x] then begin rt(fat[fat[x]]); rt(fat[x]); end else begin rt(fat[x]); lt(fat[x]); end; end else begin if rig[fat[fat[x]]]=fat[x] then begin lt(fat[fat[x]]); lt(fat[x]); end else begin lt(fat[x]); rt(fat[x]); end; end; end; procedure up1(x:longint);inline; begin if (x=0) or (fat[x]=0) then exit; if lef[fat[x]]=x then rt(fat[x]) else lt(fat[x]); end; procedure splay(x:longint);inline; begin if (x=0) or (fat[x]=0) then exit; while fat[fat[x]]>0 do up2(x); if fat[x]>0 then up2(x); head:=x; end; procedure splay2(x:longint);inline; begin if (x=0) or (fat[x]=0) then exit; while fat[fat[fat[x]]]>0 do up2(x); if fat[fat[x]]>0 then up1(x); end; function getrank(x,y:longint):longint;inline; begin if (x=0) then exit(0); ext(x); if (b[lef[x]]+1)=y then exit(x); if (b[lef[x]]+1)>y then exit(getrank(lef[x],y)) else exit(getrank(rig[x],y-1-b[lef[x]])); end; procedure turn(x,y:longint);inline; var a1,a2:longint; begin if (x=1) and (y=n) then c[head]:=1-c[head] else begin if (x=1) then begin a1:=getrank(head,y+1); splay(a1); ext(a1); c[lef[a1]]:=1-c[lef[a1]]; end else begin if (y=n) then begin a2:=getrank(head,x-1); splay(a2); ext(a2); c[rig[a2]]:=1-c[rig[a2]]; end else begin a1:=getrank(head,x-1); a2:=getrank(head,y+1); splay(a2);splay2(a1); ext(a2);ext(a1); c[rig[a1]]:=1-c[rig[a1]]; end; end; end; end; function showoff(x:longint):ansistring;inline; var s1:ansistring; begin if x=0 then exit(''); ext(x); str(x,s1); exit(showoff(lef[x])+s1+' '+showoff(rig[x])); end; begin readln(n,m); for i:=1 to n do begin a[i]:=i;c[i]:=0;b[i]:=1; end; head:=1; for i:=2 to n do begin ins(head,i); splay(random(i)+1); end; for i:=1 to m do begin readln(a1,a2); turn(a1,a2); end; s1:=showoff(head); writeln(s1); readln; end.
相关文章推荐
- 算法模板——splay区间反转 2
- 算法模板——线段树2(区间加+区间乘+区间求和)
- 算法模板——线段树3(区间覆盖值+区间求和)
- hdu 1890 Robotic Sort(splay 区间反转+删点)
- NOIP算法每周过之 线段树 区间 区间修改 区间查值 模板
- 平衡树 splay区间翻转 模板
- HDU-3487 Play with Chain Splay tee区间反转,移动
- Splay(区间翻转) 模板
- Splay 区间信息的维护与查询 静态模板
- Splay 区间维护模板
- bzoj3223[Tyvj 1729] 文艺平衡树(splay模板题:区间翻转)
- 算法模板——线段树1(区间加法+区间求和)
- 小练习,splay区间反转
- POJ2104 K-th Number (子区间内第k大的数字)【划分树算法模板应用】
- POJ 3468 A simple problem with integers Splay 区间维护模板题
- Splay_Tree 模板(区间修改,旋转操作)
- 算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)
- HDU 1754 I Hate It (splay区间最值单点修改模板)
- 郁闷的出纳员 (splay的区间标记模板,删除区间,add标记,类似线段树)
- Duan2baka的Splay模板!(区间翻转)