http://www.lydsy.com/JudgeOnline/problem.php?id=1269
1269: [AHOI2006]文本编辑器editor Input Output Sample Input Sample Output
对输入数据我们有如下假定: MOVE操作不超过50 000个,INSERT、DELETE和ROTATE操作作的总个数不超过6 000,GET操作不超过20 000个,PREV和NEXT操作的总个数不超过20 000。 所有INSERT插入的字符数之和不超过2M(1M=1 024*1 024)。 DELETE操作、ROTATE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。 输入文件没有错误。
|
裸Splay。有几个问题导致调了很长时间……
1、update旋转标记时千万不要忘记清空自身标记,同时子树的标记应该取反,而非直接赋false
2、update最好过程内直接操作本身、左右子树,这样不容易写错。
3、pushup时一定要记得更新其父亲各节点!
program editor; //Splay Tree //By HT 2012/12 //BZOJ P1269 //AHOI2004 Editor {$DEFINE INDEBUG} Type node=longint; rec=record lch,rch,f,s:longint; w:char; ro:boolean; end; Var q:array[0..2000000] of rec; ss:array[0..10000] of char; h,null,now:node; top,i,j,k,n:longint; c:char; Procedure fopen; begin assign(input,'editor.in'); assign(output,'editor.out'); reset(input); rewrite(output); end; Procedure fclose; begin close(input); close(output); end; Function mmin(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end; Procedure new(var p:node); begin inc(top); p:=top; end; Procedure pushup(P:node); begin while p<>null do begin q[p].s:=q[q[p].lch].s+q[q[p].rch].s+1; p:=q[p].f; end; end; Procedure oldupdate(P:node); var y:node; begin if p=null then exit; if q[p].ro then begin y:=q[p].lch; q[p].lch:=q[p].rch; q[p].rch:=y; if q[p].lch<>null then q[q[p].lch].ro:=not q[q[p].lch].ro; if q[p].rch<>null then q[q[p].rch].ro:=not q[q[p].rch].ro; q[p].ro:=false; end; end; Procedure update(P:node); begin oldupdate(q[p].lch); oldupdate(q[p].rch); oldupdate(p); end; Procedure zig(P:node);// LeftRonate var newroot:node; begin if p=null then exit; update(p); if q[p].rch=null then exit; newroot:=q[p].rch; q[newroot].f:=q[p].f; if q[p].f<>null then if q[q[p].f].lch=p then q[q[p].f].lch:=newroot else q[q[p].f].rch:=newroot else h:=newroot; q[p].rch:=q[newroot].lch; if q[p].rch<>null then q[q[p].rch].f:=p; q[newroot].lch:=p; q[p].f:=newroot; pushup(p); pushup(newroot); end; Procedure zag(P:node);//RightRonate var newroot:node; begin if p=null then exit; update(p); if q[p].lch=null then exit; newroot:=q[p].lch; q[newroot].f:=q[p].f; if q[p].f<>null then if q[q[p].f].lch=p then q[q[p].f].lch:=newroot else q[q[p].f].rch:=newroot else h:=newroot; q[p].lch:=q[newroot].rch; if q[p].lch<>null then q[q[p].lch].f:=p; q[newroot].rch:=p; q[p].f:=newroot; pushup(p); pushup(newroot); end; Procedure Splay(P,tar:node); var x,y,z:node; begin if p=null then exit; x:=p; while q[x].f<>tar do begin y:=q[x].f; z:=q[y].f; update(z); update(y); update(x); if z=tar then begin if q[y].lch=x then zag(y) else zig(y); exit; end; if (q[z].lch=y) and (q[y].lch=x) then begin zag(z); zag(y); end else if (q[z].rch=y) and (q[y].rch=x) then begin zig(z); zig(y); end else if (q[z].lch=y) and (q[y].rch=x) then begin zig(y); zag(z); end else begin zag(y); zig(z); end; end; end; Function kth(P:longint):node; begin kth:=h; update(kth); if p>q[h].s then p:=q[h].s; while q[kth].s>1 do begin if q[q[kth].lch].s+1=p then exit; if p<q[q[kth].lch].s+1 then kth:=q[kth].lch else begin dec(p,q[q[kth].lch].s+1); kth:=q[kth].rch; end; update(kth); end; end; Function buildtree(pl,pr:longint):node; var mid:longint; ans:node; begin if pr<pl then exit(null); if pl=pr then begin new(ans); with q[ans] do begin s:=1; w:=ss[pl]; lch:=null; rch:=null; f:=null; ro:=false; end; exit(ans); end; mid:=(pl+pr) div 2; new(ans); with q[ans] do begin s:=pr-pl+1; w:=ss[mid]; ro:=false; lch:=buildtree(pl,mid-1); rch:=buildtree(mid+1,pr); if lch<>null then q[lch].f:=ans; if rch<>null then q[rch].f:=ans; exit(ans); end; end; Procedure Insert(k:longint); var p:node; begin p:=now; update(p); if q[p].rch=null then begin q[p].rch:=buildtree(1,k); q[q[p].rch].f:=p; pushup(p); exit; end; p:=q[p].rch; update(p); while q[p].lch<>null do begin p:=q[p].lch; update(p); end; q[p].lch:=buildtree(1,k); q[q[p].lch].f:=p; pushup(p); end; Procedure move(P:longint); begin now:=h; update(now); while q[now].s>1 do begin if q[q[now].lch].s+1=p then exit; if p<q[q[now].lch].s+1 then now:=q[now].lch else begin dec(p,q[q[now].lch].s+1); now:=q[now].rch; end; update(now); end; end; Procedure next; var o:node; begin update(now); if q[now].rch<>null then begin now:=q[now].rch; update(now); while q[now].lch<>null do begin now:=q[now].lch; update(now); end; end else begin o:=q[now].f; update(o); while o<>null do begin if q[o].lch=now then break; o:=q[o].f; now:=q[now].f; update(o); end; now:=o; end; splay(now,null); end; Procedure prev; var o:node; begin update(now); if q[now].lch<>null then begin now:=q[now].lch; update(now); while q[now].rch<>null do begin now:=q[now].rch; update(now); end; end else begin o:=q[now].f; update(o); while o<>null do begin if q[o].rch=now then break; o:=q[o].f; now:=q[now].f; update(o); end; now:=o; end; splay(now,null); end; Function Getpos:longint; var p,qq:node; begin p:=q[now].f; qq:=now; getpos:=q[q[now].lch].s+1; // if now=null then error(renone); update(p); update(qq); while p<>null do begin if q[p].rch=qq then inc(getpos,q[q[p].lch].s+1); p:=q[p].f; qq:=q[qq].f; update(p); update(qq); end; end; Procedure get; var oldnow:node; begin oldnow:=now; if q[h].s<>getpos then begin next; writeln(q[now].w); end else writeln(' '); now:=oldnow; splay(now,null); end; Procedure delete(P:longint); var tmp:node; begin tmp:=kth(mmin(q[h].s,getpos+p+1)); splay(now,null); splay(tmp,h); update(h); update(q[h].rch); update(q[h].lch); q[q[h].rch].lch:=null; pushup(q[h].rch); end; Procedure ronate(P:longint); var tmp:node; begin tmp:=kth(mmin(q[h].s,getpos+p+1)); splay(now,null); splay(tmp,h); update(q[q[h].rch].lch); update(q[h].rch); update(h); q[q[q[h].rch].lch].ro:=true; //q[q[h].rch].lch:=null; end; Procedure init; var p:node; begin top:=0; new(null); with q[null] do begin s:=0; lch:=null; rch:=null; f:=null; w:=#0; end; new(h);now:=h; with q[h] do begin lch:=null; rch:=null; f:=null; w:=#0; s:=1; end; for i:=1 to 10 do ss[i]:=#0; insert(10); end; Procedure readchar(P:longint); var i:longint; o:char; begin for i:=1 to p do read(o); end; begin {$IFDEF INDEBUG} fopen; {$ENDIF} readln(n); init; for i:=1 to n do begin read(c); case c of 'M': begin readchar(3); readln(k); move(k+1); end; 'I': begin readchar(5); readln(k); for j:=1 to k do read(ss[j]); readln; insert(k); end; 'D': begin readchar(5); readln(k); delete(k); end; 'R': begin readchar(5); readln(k); ronate(k); end; 'G': begin get; readchar(2); readln; end; 'P': begin prev; readchar(3); readln; end; 'N': begin next; readchar(3); readln; end; end; // writeln('No.',i,' Succeed! '); //flush(output); //get; end; {$IFDEF INDEBUG} fclose; {$ENDIF} end.