tyvj 1729 文藝平衡樹

2022-05-12 12:23:48 字數 3994 閱讀 2875

文藝平衡樹

fromadmin

背景 background

此為平衡樹系列第二道:文藝平衡樹

描述 description

您需要寫一種資料結構(可參考題目標題),來維護乙個有序數列,其中需要提供以下操作:

翻轉乙個區間,例如原有序序列是5 4 3 2 1,翻轉區間是[2,4]的話,結果是5 2 3 4 1

輸入格式 inputformat

第一行為n,m n表示初始序列有n個數,這個序列依次是(1,2……n-1,n)  m表示翻轉操作次數

接下來m行每行兩個數[l,r] 資料保證 1<=l<=r<=n

輸出格式 outputformat

輸出一行n個數字,表示原始序列經過m次變換後的結果

樣例輸入 sampleinput [複製資料]

5 31 3

1 31 4

樣例輸出 sampleoutput [複製資料]

4 3 2 1 5 

資料範圍和注釋 hint

n,m<=100000 

題解:終於a了這道題,好激動。。。

也終於找到了乙個好的splay模版

向序列之神--splay進發!

**:

1

const maxn=100000+100;2

var s,id,fa:array[0..maxn] of

longint;

3 rev:array[0..maxn] of

boolean;

4 c:array[0..maxn,0..1] of

longint;

5i,n,m,rt,x,y:longint;

6procedure swap(var

x,y:longint);

7var

t:longint;

8begin

9 t:=x;x:=y;y:=t;

10end;11

12procedure

pushup(x:longint);

13begin

14 s[x]:=s[c[x,0]]+s[c[x,1]]+1;15

end;

16procedure

pushdown(x:longint);

17var

l,r:longint;

18begin

19 l:=c[x,0];r:=c[x,1

];20

if rev[x] then

21begin

22 swap(c[x,0],c[x,1

]);23 rev[l]:=not

(rev[l]);

24 rev[r]:=not

(rev[r]);

25 rev[x]:=false;

26end;27

end;

28procedure rotate(x:longint;var

k:longint);

29var

l,r,y,z:longint;

30begin

31 y:=fa[x];z:=fa[y];

32if c[y,0]=x then l:=0

else l:=1;r:=l xor 1;33

if y=k then k:=x else c[z,ord(c[z,1]=y)]:=x;

34 fa[x]:=z;fa[y]:=x;fa[c[x,r]]:=y;

35 c[y,l]:=c[x,r];c[x,r]:=y;

36pushup(y);pushup(x);

37end;38

procedure splay(x:longint;var

k:longint);

39var

y,z:longint;

40begin

41while x<>k do

42begin

43 y:=fa[x];z:=fa[y];

44if y<>k then

45begin

46if (c[z,0]=y) xor (c[y,0]=x) then

rotate(x,k)

47else

rotate(y,k);

48end;49

rotate(x,k);

50end;51

end;

52function

find(x,rank:longint):longint;

53var

l,r:longint;

54begin

55 pushdown(x);l:=c[x,0];r:=c[x,1

];56

if s[l]+1=rank then

exit(x)

57else

if s[l]>=rank then

exit(find(l,rank))

58else exit(find(r,rank-s[l]-1

));59

end;

60procedure

rever(l,r:longint);

61var

x,y:longint;

62begin

63 x:=find(rt,l);y:=find(rt,r+2

);64 splay(x,rt);splay(y,c[x,1

]);65 rev[c[y,0]]:=not(rev[c[y,0

]]);

66end;67

procedure

build(l,r,f:longint);

68var

mid,now,last:longint;

69begin

70if l>r then

exit;

71 now:=id[l];last:=id[f];

72if l=r then

73begin

74 fa[now]:=last;s[now]:=1

;75 c[last,ord(l>f)]:=now;

76exit;

77end

;78 mid:=(l+r)>>1

;79 build(l,mid-1,mid);build(mid+1

,r,mid);

80 now:=id[mid];pushup(mid);

81 fa[now]:=last;

82 c[last,ord(mid>f)]:=now;

83end;84

procedure

init;

85begin

86readln(n,m);

87for i:=1

to n+2

do id[i]:=i;

88 build(1,n+2,0);rt:=(n+3)>>1;89

end;

90procedure

main;

91begin

92for i:=1

to m do

93begin

94readln(x,y);

95rever(x,y);

96end;97

for i:=2

to n+1

do write(find(rt,i)-1,'');

98end;99

begin

100 assign(input,'

input.txt

');assign(output,'

output.txt');

101reset(input);rewrite(output);

102init;

103main;

104close(input);close(output);

105end

.106

view code

Tyvj 1729 文藝平衡樹

題面如下 time limit 1 sec memory limit 128 mb 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 翻轉乙個區間,例如原有序序列是5 4 3 2 1,翻轉區間是 2,4 的話,結果是5 2 3 4 1 第一行為n,m n表示初始序列有n...

bzoj3223 Tyvj 1729 文藝平衡樹

傳送門 description input 第一行為n,m n表示初始序列有n個數,這個序列依次是 1,2 n 1,n m表示翻轉操作次數 接下來m行每行兩個數 l,r 資料保證 1 l r n output 輸出一行n個數字,表示原始序列經過m次變換後的結果 sample input 5 31 3...

BZOJ3223 Tyvj1729 文藝平衡樹

題目大意 一開始有個數列 有q 次區間翻轉操作。請輸出最後的序列。1 n,q 105一道寫出blog都不知道有什麼意義的splay大裸題。splay在我還是pas黨的時候寫過,現在已經忘了個精光。就當做是模板記錄,以及作為自己終於下定決心怒剛專題的紀念吧。什麼你告訴我你不知道這題怎麼做?那我也沒辦法...