NOI2005 維護數列

2022-06-03 05:09:15 字數 2352 閱讀 7873

一道伸展樹維護數列的很悲傷的題目,共要維護兩個標記和兩個數列資訊,為了維護max-sum還要維護從左端開始的數列的最大和及到右端結束的數列的最大和。

按照伸展樹的套路,給數列左右兩邊加上不存在的邊界節點,給每個子樹的空兒子指向哨兵節點。

題目說的子數列其實要求至少包含乙個元素,這就要很噁心的維護方法。

(其實讓max_sum可以不含元素也能過90%)

每個節點定義max_sum:該節點的最大數列和(至少包含乙個元素)

max_lsum:該節點的從左端開始的最大數列和(可以不包含元素)

max_rsum:該節點的到右端結束的最大數列和(可以不包含元素)

按照分冶法,max_sum=max。

如果它和它的左右兒子都是普通節點,這個轉移保證至少有乙個元素。

如果它是普通節點或邊界節點,它的左或右兒子是哨兵節點,則左兒子max_sum或右兒子max_sum是不可取的。故令哨兵節點的max_sum=-inf。

如果它是邊界節點,它必定至多有乙個兒子,令它的max_sum等於它的唯一兒子的max_sum,max_lsum與max_rsum同理。

每個節點定義兩個標記replaced和reversed。

replaced:這個節點及它的所有後代都應該修改為乙個特定的值,但實際上只有這個節點的值已經修改。

reversed:這個節點及它的所有後代都應該交換左右子樹(max_lsum和max_rsum也應該跟著交換),但實際上只有這個節點的左右子樹已經交換。

可見這兩個標記是互斥的,且replaced標記的優先順序顯然大於reversed標記。

打標記的時候注意維護每個結點的標記至多有乙個就可以了。

350行的不壓行**,6.33kb,調了近8小時交了差不多二十遍才ac:

#include #include 

#include

#include

using

namespace

std;

void getstr(string &s)

dos += (char

)c;

while (isalpha(c = getchar()) || c == '-'

);}void getint(int &x)

dox = x * 10 + c - '0'

;

while (isdigit(c =getchar()));

if(flag)

x = -x;

}namespace

splay

;struct

node;

node *nil = 0, *l_edge, *r_edge;

struct

node

}int cmp(int

k)

void

reverse()

}void replace(int

v)

}void

push_down()

else

if(reversed)

}void

pull_up()

else

if (this == l_edge) //

注意特判左右邊界節點

else}}

void

remove()

}} *root;

void

init()

void rotate(node *&t, int

d)void splay(node *&t, int

k)

else

}else

rotate(t, d ^ 1

); }

}void join(node *&t1, node *&t2)

node *split(node *&t, int

k) splay(t, k);

node *subtree = t->ch[r];

t->ch[r] =nil;

t->pull_up();

return

subtree;

}node *build_tree(int *p, int

n)

return

fa;}

node *select(int p, int

tot)

}int

n, m;

int num[500005

];int

main()

else

//max_sum

cout << root->max_sum

; }

}return0;

}

noi2005維護數列

請寫乙個程式,要求維護乙個數列,支援以下 6 種操作 請注意,格式欄 中的下劃線 表示實際輸入檔案中的空格 操作編號 輸入檔案中的格式 說明1.插入 insert posi tot c1 c2 c tot 在當前數列的第 posi 個數字後插入 tot 個數字 c1,c2,c tot 若在數列首插 ...

NOI2005 維護數列

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

NOI2005 維護數列

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