[BZOJ3223] Tyvj 1729 文艺平衡树

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=3223

题目大意

[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.

你可能感兴趣的:([BZOJ3223] Tyvj 1729 文艺平衡树)