NOI2005 維修數列

2022-05-12 12:10:22 字數 3366 閱讀 1024

輸入的第1 行包含兩個數n 和m(m ≤20 000),n 表示初始時數列中數的個數,m表示要進行的運算元目。 第2行包含n個數字,描述初始時的數列。 以下m行,每行一條命令,格式參見問題描述中的**。 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在[-1 000, 1 000]內。 插入的數字總數不超過4 000 000個,輸入檔案大小不超過20mbytes。

對於輸入資料中的get-sum和max-sum操作,向輸出檔案依次列印結果,每個答案(數字)佔一行。

9 82 -6 3 5 1 -5 -3 6 3

get-sum 5 4

max-sum

insert 8 3 -5 7 2

delete 12 1

make-same 3 3 2

reverse 3 6

get-sum 5 4

max-sum

-110110

題解:

splay,幾乎所有模式都在裡面

注意這個splay維護的是位置

插入:將第pos旋到根,第pos+1(名次樹操作)旋到根的右子樹

這裡的插入用了一種二分的方法,可以保證有序,且可以直接反轉

刪除:將第pos旋到根,第pos+tot+1旋到根的右子樹

如果用了記憶體池還要遞迴**(詳見erase)

反**留下反轉標記,每次直接交換左右節點

修改同上,注意0

求和直接維護

求最大子串行和有點複雜,維護節點最大子串行和,右端最大和,左端最大和,詳見(pushdown)

1 #include2 #include3 #include4 #include5

using

namespace

std;

6const

int maxn=500010;7

int tot2,tot1,s[maxn],pre[maxn],ch[maxn][2

],key[maxn],sum[maxn],maxsum[maxn],lx[maxn],rx[maxn],a[maxn];

8int

size[maxn],same[maxn],root,n,m;

9bool

rev[maxn];

10int

gi()

1115

while (ch>='

0'&&ch<='9'

)16

17return s*sign;18}

19void newnode(int &r,int fa,int

k)20

32void pushup(int

x)33

42void update_same(int x,int

c);43

void update_reverse(int

x);44

void pushdown(int

x)45

52if

(rev[x])

5358}59

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

fa)60

68int getkth(int r,int

k)69

76void rotate(int x,bool

t)77

89void splay(int x,int

goal)

90100

else

101111

else

112116

}117

}118

pushup(x);

119if (goal==0) root=x;

120}

121void insert(int pos,int

tot)

122

127 splay(getkth(root,pos+1),0

);128 splay(getkth(root,pos+2

),root);

129 build(ch[ch[root][1]][0],1,tot,ch[root][1

]);130 pushup(ch[root][1

]);131

pushup(root);

132}

133void erase(int

r)134

140void delete(int pos,int

tot)

141150

void update_same(int x,int

c)151

158void make_same(int pos,int tot,int

c)159

166void update_reverse(int

x)167

173void reverse(int pos,int

tot)

174181

int getsum(int pos,int

tot)

182187

intmax_sum()

188193

intmain()

194

201 lx[root]=rx[root]=maxsum[root]=-2e9;

202 newnode(root,0,-1

);203 newnode(ch[root][1],root,-1

);204 build(ch[ch[root][1]][0],1,n,ch[root][1

]);205 pushup(ch[root][1

]);206

pushup(root);

207for (i=1; i<=m; i++)

208215

else

if (str[0]=='d'

)216

220else

if (str[0]=='

m'&&str[4]=='-'

)221

225else

if (str[0]=='r'

)226

231else

if (str[0]=='g'

)232

237else

if (str[0]=='

m'&&str[3]=='-'

)238

241}

242 }

NOI 2005 維修數列

noi 2005 維修數列 典型的伸展樹模板題 參考 include include include include include using namespace std define key value ch ch root 1 0 const int maxn 500010 const int...

維修數列 NOI2005

好久沒寫題解了 來水一篇題解 請寫乙個程式,要求維護乙個數列,支援以下 6 種操作 輸入的第1行包含兩個數 n 和 m m leq 20 000 n 表示初始時數列中數的個數,m 表示要進行的運算元目。第2行包含 n 個數字,描述初始時的數列。以下 m 行,每行一條命令,格式參見問題描述中的 任何時...

1500 NOI2005 維修數列

題目思路 splay 包括區間插入,區間刪除,記憶體,區間反轉,區間和,區間最大子段,成段更新等操作。include include include include include include include include include include includeusing namesp...