一練Splay之維修數列第一次

2022-05-27 22:33:16 字數 3965 閱讀 6028

平衡樹並不是之前沒寫過,覺得有必要把平衡樹變成考場上能敲的東西,也就是說,考一道諸如「維修數列」這樣的送分題,要能拿滿分。

維修數列。給定乙個數列支援以下操作:

輸入的第1 行包含兩個數n 和m(m ≤20 000),n 表示初始時數列中數的個數,m表示要進行的運算元目。

第2行包含n個數字,描述初始時的數列。

以下m行,每行一條命令,格式參見問題描述中的**。

任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在[-1 000, 1 000]內。

插入的數字總數不超過4 000 000個,輸入檔案大小不超過20mbytes。

以上都是複製的。

這一次呢肯定比上一次敲的快了那麼一點,但沒有達到要求,總時間大概3h,還需很大的提公升。

除錯時間。。inf

主要的除錯時間在邊界的處理上。

1、某個子樹大小。本來子樹大小如果不影響答案計算的話是可以直接把邊界加進來的,但是這裡有求和和區間賦值,因此有必要知道區間除了邊界外的真實大小。

這一次的處理方式是:假設邊界點是不存在的,即size=0.這樣引發的一系列調整如下:

首先,up時size的更新要注意不要加上邊界點:

a[x].size=a[p].size+a[q].size+(x!=lbod && x!=rbod);
其次,find時對邊界點單獨處理下:

if (k>a[root].size) ans=rbod;

else

if (k==0) ans=lbod;

在find時,找第k個數,如果往右走要這麼寫:

k-=a[x].size-a[a[x].son[1]].size,x=a[x].son[1];
而不要寫k-=a[a[x].son[0]].size+1,這樣相當於預設x的size是1,而x有可能是邊界點。

2、連邊必up,訪子必down。up和down在一些細節會忘了打。最典型的是splay:splay(x,top)表示把x旋到top下,如果top不為0的話應up(top);再如find以及其他類似操作時心存僥倖以為不用down,但實際上這題有區間翻轉操作,左右兒子會變,因此必須down。

3、讀入。注意'-'號。

4、答案。注意邊界點既要做到能傳遞區間答案,本身又不能對答案產生影響。這裡解決的方法是在up的時候進行如下判斷:

if (x!=lbod && x!=rbod) a[x].maxsum=max(a[p].maxsum,max(a[q].maxsum,a[p].rsum+a[x].v+a[q].lsum));

else

if (x==lbod) a[x].maxsum=q?a[q].maxsum:-0x3f3f3f3f

;

else a[x].maxsum=p?a[p].maxsum:-0x3f3f3f3f;

以及在區間賦值時進行如下操作:

if (x==lbod || x==rbod) a[x].v=0

;

if (a[x].size==0) a[x].lsum=a[x].rsum=a[x].maxsum=-0x3f3f3f3f;

除錯時果斷選擇區間輸出。但靜態查錯還是不能少。

總的來說,有待提高。

1 #include

2 #include3 #include4

//#include

5 #include6

//#include

7using

namespace

std;89

intn,m;

10#define maxn 500011

11int

num[maxn];

1213

struct

splay

14a[maxn];

21int

root,sta[maxn],top,lbod,rbod;

22splay()

2333

void up(int

x)34

45void besingle(int x,int

v)46

55void revsingle(int

x)56

61void down(int

x)62

65if (a[x].rev) 66}

67int

dsta[maxn],dtop;

68void download(int

x)69

74void rotate(int

x)75

86void splay(int x,int

top)

8798

rotate(x);99}

100up(x);

101if (!top) root=x; else

up(top);

102}

103int find(int

k)104

118if (ans) splay(ans,0

);119

return

ans;

120}

121void new(int &x)

122void build(int &x,int l,int

r)123

125new(x);

126//

cout<127

const

int mid=(l+r)>>1

;128 a[x].v=a[x].sum=a[x].maxsum=num[mid]; a[x].size=1; a[x].hbe=a[x].rev=0

;129

if (num[mid]>=0) a[x].lsum=a[x].rsum=num[mid];

130else a[x].lsum=a[x].rsum=0

;131 build(a[x].son[0],l,mid-1

);132

if (a[x].son[0]) a[a[x].son[0]].fa=x;

133 build(a[x].son[1],mid+1

,r);

134if (a[x].son[1]) a[a[x].son[1]].fa=x;

135up(x);

136}

137void build(int &x,int n)

138void insert(int pos,int

tot)

139148

void recycle(int

x)149

154void delete(int pos,int

tot)

155164

void be(int pos,int tot,int

v)165

171void rev(int pos,int

tot)

172178

int sum(int pos,int

tot)

179188

int maxsum()

189//

void test(int x)

190//

199//

void test() t;

201202

intqread()

203207

intmain()

208225

else

if (c=='d'

)226

231else

if (c=='r'

)232

237else

if (c=='g'

)238

243else

244252

else

253257

}258

259//

t.test();

260}

261return0;

262 }

view code

第一次筆記本維修經歷

現在我在長沙的hp維修中心,心情有些鬱悶。在家使用本本時老出現的問題現在就是不出現,而維修工程師又說必須要看到問題現象才好檢測,我不能就這麼空等下去吧。雖然這裡正在放映我還沒看的阿凡達,雖然這裡可以免費上網,但我是來修本本的啊。這該死的問題怎麼現在就是不出現,等了也近乙個小時了。這裡真是很忙,來維修...

第一次機房之結賬

結賬是做機房遇到的難點之一,難在是第一次接觸結賬計算功能,所以很多情況考慮不夠全面,做之前一定要梳理關係,把結賬的關係梳理清楚,有乙個自己的思路,那麼,做起來還是很簡單的,每乙個功能都有它的套路,只要找到了關鍵的部分,剩下的就是去做了。如 購卡 連線資料庫 txtsql select from st...

第一次飛行

開始敲下這段話時,窗外下面正是一片片陽光照耀著的白雲,伴隨著張學友的歌聲,心潮起伏.雖然從初中起,我就經常乙個人坐著火車,汽車東奔西跑,坐飛機卻是第一次.早上上飛機前,心裡忐忑,必竟還是踏在陸地上踏實.但上了飛機後注意力就放在其它地方上去了,而且,運氣好的是我有乙個靠窗的位置.飛機準備起飛了,助跑加...