1. 程式人生 > >[BZOJ3223] Tyvj 1729 文藝平衡樹

[BZOJ3223] Tyvj 1729 文藝平衡樹

傳送門

題目大意

[1,n],每次翻轉[L,R],輸出最後的序列

題解

Splay模板題
翻轉標記下放注意的細節在code裡
Splay第一題~~

const
 maxn=100005;
var
 w:array[-1..maxn,1..6]of longint;  //1:左兒子 2:右兒子 3:父 4:子樹節點數 5:權值 6:翻轉標記
 i,j,k:longint;
 n,m,l,r,root,sum:longint;
procedure swap(var a,b:longint);
var c:longint;
begin c:=a; a:=b; b:=c; end;

procedure
pushdown(a:longint);
begin w[a,6]:=-1; swap(w[a,1],w[a,2]); if w[w[a,1],6]=1 then w[w[a,1],6]:=-1 else w[w[a,1],6]:=1; if w[w[a,2],6]=1 then w[w[a,2],6]:=-1 else w[w[a,2],6]:=1; end; procedure rotate(a,kind:longint); //右旋:1左旋:2 var unkind:longint; begin unkind:=kind xor 3; //因為向下尋找的時候就把從root到那個點的路徑上的標記都下放了,所以不用再下放
w[a,4]:=w[w[a,3],4]; w[w[a,3],4]:=w[w[a,unkind],4]+w[w[w[a,3],unkind],4]+1; w[w[a,3],kind]:=w[a,unkind]; w[w[a,unkind],3]:=w[a,3]; w[a,unkind]:=w[a,3]; w[a,3]:=w[w[a,3],3]; w[w[a,unkind],3]:=a; if w[a,3]<>-1 then if w[w[a,3],2]=w[a,unkind] then w[w[a,3],2]:=a else w[w[a,3],1]:=a; end
; procedure splay(a,goal:longint); var kind,unkind:longint; begin while w[a,3]<>goal do begin if w[w[a,3],1]=a then kind:=1 else kind:=2; unkind:=kind xor 3; if w[a,6]=1 then pushdown(a); if w[w[a,3],3]=goal then rotate(a,kind) else if w[w[w[a,3],3],kind]=w[a,3] then begin rotate(w[a,3],kind); rotate(a,kind); end else begin rotate(a,kind); rotate(a,unkind); end; end; if goal=-1 then root:=a; end; procedure init(a:longint); var tt,fa,kind:longint; begin tt:=root; while tt<>-1 do begin fa:=tt; if a<w[tt,5] then begin tt:=w[tt,1]; kind:=1; end else begin tt:=w[tt,2]; kind:=2; end; end; inc(sum); w[sum,1]:=-1; w[sum,2]:=-1; w[sum,3]:=fa; w[sum,4]:=1; w[sum,5]:=a; w[sum,6]:=-1; w[fa,kind]:=sum; inc(w[fa,4]); splay(sum,-1); end; function find(rank:longint):longint; //rank表示它前面有rank個它是第rank+1個 var tt:longint; begin tt:=root; if w[tt,6]=1 then pushdown(tt); //向下尋找時要先下方標記,防止下放了,while的條件就滿足了的情況 while w[w[tt,1],4]<>rank do begin if w[w[tt,1],4]<rank then begin dec(rank,w[w[tt,1],4]+1); tt:=w[tt,2]; end else tt:=w[tt,1]; if w[tt,6]=1 then pushdown(tt); end; exit(tt); end; procedure print(a:longint); begin if w[a,6]=1 then pushdown(a); if w[a,1]<>-1 then print(w[a,1]); if (w[a,5]<>0)and(w[a,5]<>n+1) then write(w[a,5],' '); if w[a,2]<>-1 then print(w[a,2]); if (a=root) then writeln; end; begin readln(n,m); sum:=1; root:=1; w[1,1]:=-1; w[1,2]:=-1; w[1,3]:=-1; w[1,4]:=1; w[1,5]:=0; w[1,6]:=-1; for i:=1 to n+1 do init(i); for i:=1 to m do begin readln(l,r); splay(find(l-1),-1); splay(find(r+1),root); if w[w[w[root,2],1],6]=-1 then w[w[w[root,2],1],6]:=1 else w[w[w[root,2],1],6]:=-1; end; print(root); end.