noi2005維護數列

2021-07-28 01:46:00 字數 4043 閱讀 6852

請寫乙個程式,要求維護乙個數列,支援以下 6 種操作:(請注意,格式欄 中的下劃線『 _ 』表示實際輸入檔案中的空格)

操作編號

輸入檔案中的格式

說明1.  插入

insert_posi_tot_c1_c2_..._c

tot

在當前數列的第 posi 個數字後插入 tot

個數字:c1, c2, …, c

tot;若在數列首插

入,則 posi 為 0

2.  刪除

delete_posi_tot

從當前數列的第 posi 個數字開始連續

刪除 tot 個數字

3.  修改

make-same_posi_tot_c

將當前數列的第 posi 個數字開始的連

續 tot 個數字統一修改為 c

4.  翻轉

reverse_posi_tot

取出從當前數列的第 posi 個數字開始

的 tot 個數字,翻轉後放入原來的位置

5.  求和

get-sum_posi_tot

計算從當前數列開始的第 posi 個數字

開始的 tot 個數字的和並輸出

6.  求和最

大的子列

max-sum

求出當前數列中和最大的一段子列,

並輸出最大和

【輸入格式】

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

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

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

【輸出格式】

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

【輸入樣例】

9 8

2 -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

【輸出樣例】

-1101

10

【樣例說明】

初始時,我們擁有數列 2 -6 3 5 1 -5 -3 6 3

執行操作 get-sum 5 4,表示求出數列中從第 5 個數開始連續 4 個數字之和,1+(-5)+(-3)+6 = -1:

2     -6     3      5      1     -5    -3     6      3
執行操作 max-sum,表示要求求出當前數列中最大的一段和,應為 3+5+1+(-5)+(-3)+6+3 = 10:

2     -6     3      5      1     -5    -3     6      3
執行操作 insert 8 3 -5 7 2,即在數列中第 8 個數字後插入-5 7 2,

2     -6     3      5      1     -5    -3     6     -5     7      2      3
執行操作 delete 12 1,表示刪除第 12 個數字,即最後乙個:

2     -6     3      5      1     -5    -3     6     -5     7      2
執行操作 make-same 3 3 2,表示從第 3 個數開始的 3 個數字,統一修改為 2:

2	-6	3	5	1	-5	-3	6	-5	7	2
改為

2	-6	2	2	2	-5	-3	6	-5	7	2
執行操作 reverse 3 6,表示取出數列中從第 3 個數開始的連續 6 個數:

2           -6            2             2             2           -5            -3            6            -5            7            2
如上所示的灰色部分 2 2 2 -5 -3 6,翻轉後得到 6 -3 -5 2 2 2,並放回原來位置:

2     -6     6     -3     -5     2      2      2     -5     7      2
最後執行 get-sum 5 4 和 max-sum,不難得到答案 1 和 10。

2            -6            6            -3            -5           2             2            2             -5           7             2
【評分方法】

本題設有部分分,對於每乙個測試點:

請注意:如果你的程式只能正確處理某一種操作,請確定在輸出檔案正確的位置上列印結果,即必須為另一種操作留下對應的行,否則我們不保證可以正確評分。

【資料規模和約定】

splay維護數列模板題,我們認為該splay的中序遍歷即為原數列,那麼處理區間只需將該區間左邊界點左相鄰點旋轉至樹根,將區間右邊界點右相鄰點旋轉至樹根右兒子,則樹根右兒子的左兒子的子樹即為所要處理的區間,

**:

#include #include #include #include #include #include using namespace std;

string s;

const int maxn=500000+10;

queueq;

const int inf=0x7fffffff;

int tr[maxn][3];

int root;

int rotated[maxn]=;

long long summ[maxn]=;

long long maxx[maxn]=;

int fa[maxn];

int n;

int id[maxn];

int a[maxn];

int v[maxn];

long long lmax[maxn];

long long rmax[maxn];

int size[maxn];

int cnt;

int tag[maxn];

inline void pushup(int x)

inline void pushdown(int x)

else

} if(rotated[x])

}inline void rotate(int x,int& o)

inline void splay(int x,int& k)

rotate(x,k); }}

inline int find(int o,int k)

inline void dec(int x)

inline int spilt(int o,int tot)

inline void sum(int o,int k)

inline void modify(int k,int tot,int val)

inline void rev(int o,int k)

}inline void del(int o,int k)

inline void build(int l,int r,int f)

else

v[now]=a[mid];

fa[now]=last;

pushup(now);

tr[last][mid>=f]=now;

}inline void insert(int k,int tot)

inline void dfs(int x)

int main()

if(s[0]=='r')

rev(k,tot);

if(s[0]=='g')

sum(k,tot);

//dfs(root);

//printf("\n");

}return 0;

}

NOI2005 維護數列

陳年老題。我就 碼了4k多。主要就是用splay,然後處理區間上的東西 區間反轉就和模板一樣,但是要記得反轉leftmax和rightmax 區間賦值就把那個區間提取出來,然後給子樹根打個same標記,表示下面的全一樣。區間求最大子段和就和線段樹的套路一樣。區間插入就先弄好一顆平衡樹,然後把原平衡樹...

NOI2005 維護數列

傳送門 我還是沒有逃過在這道題上debug好久的命運 我是使用 fhq treap 來做的這道題。寫的時候寫的挺爽的 調的時候真難受。首先我們先來說說咋做吧。前5個操作對於 fhq treap 來說不在話下,只要多打兩個標記就可以了。但是如何求最大子段和?於是乎我們再打三個標記來維護它 霧 然後我們...

NOI2005 維護數列

嘟嘟嘟 這題我寫的時候還是挺順的,邊寫邊想為啥學姐說我是 勇士 然後我用了大半天的debug時間理解了這句話 先不說那幾個把人坑到退役的點,光說這幾個操作,其實都聽基礎的。我感覺唯一要說一下的就是插入一串數 我們先把這些數建成乙個splay,然後把這個splay的根節點連到對應的點的兒子節點即可。然...