超級鋼琴:
超級鋼琴
【問題描述】
小z 是乙個小有名氣的鋼琴家,最近 c 博士送給了小z一架超級鋼琴,小 z
希望能夠用這架鋼琴創作出世界上最美妙的**。
這架超級鋼琴可以彈奏出 n個音符,編號為 1至n。第i個音符的美妙度為
ai,其中ai可正可負。
乙個「超級和弦」由若干個編號連續的音符組成,包含的音符個數不少於 l
且不多於r。我們定義超級和弦的美妙度為其包含的所有音符的美妙度之和。兩
個超級和弦被認為是相同的,當且僅當這兩個超級和弦所包含的音符集合是相同
的。小z 決定創作一首由 k個超級和弦組成的樂曲,為了使得樂曲更加動聽,小
z要求該樂曲由k個不同的超級和弦組成。我們定義一首樂曲的美妙度為其所包
含的所有超級和弦的美妙度之和。小 z想知道他能夠創作出來的樂曲美妙度最大
值是多少。
【輸入格式】
輸入檔名為 piano.in。
輸入檔案第一行包含四個正整數 n, k, l, r。其中 n為音符的個數,k為樂
曲所包含的超級和弦個數, l和r分別是超級和弦所包含音符個數的下限和上限。
接下來n行,每行包含乙個整數 ai,表示按編號從小到大每個音符的美妙度。
【輸出格式】
輸出檔案為 piano.out。
輸出檔案只有乙個整數,表示樂曲美妙度的最大值。
【樣例輸入】
4 3 2 332
-68【樣例輸出】
11【樣例說明】
共有5種不同的超級和弦:
1. 音符 1 ~ 2,美妙度為 3 + 2 = 5
2. 音符 2 ~ 3,美妙度為 2 + (-6) = -4
3. 音符 3 ~ 4,美妙度為(-6) + 8 = 2
4. 音符 1 ~ 3,美妙度為 3 + 2 + (-6) = -1
5. 音符 2 ~ 4,美妙度為 2 + (-6) + 8 = 4
最優方案為:樂曲由和弦 1,和弦3,和弦 5組成,美妙度為5 + 2 + 4 = 11。
【執行時限】
2秒。【執行空限】
512m。
【資料規模和約定】
總共 10個測試點,資料範圍滿足:
題目大意:
取前k個最大的連續區間和,區間長度在[l,r]之間。
使用rmq的st演算法和堆來實現。
因此,當左邊界固定的時候,要求乙個最大的區間和,就在所有右邊界的可能取值中,找乙個字首和最大的。
這時候,rmq就隆重登場了。以前沒有想過,最大區間和和區間最大值可以這樣轉換呀。。其實很簡單的,只是我轉不過彎。
因此我們需要找到對於所有的i,[i,i+l-1]、[i,i+l]……[i,i+r-1]這些區間之中的最大值,總共有n個。
我們用堆來維護比較好。
注意:當從堆中取出乙個最大的時候,可能對於這個i,[i,i+l-1]、[i,i+l]……[i,i+r-1]這些區間之中的次大值,會比對於其他i的最大值更大。
因此我們需要將這些區間重新放回去,除開[i,i+pos-1],假設i+pos-1是原來的最大值。實現方法參見wjj的部落格whjpji。
這道題確實很巧妙呀我覺得。
兩個版本最後兩個點都超時,想不出辦法來了。
手寫堆版:
#include #include //#include #define max(a,b) (a>b?a:b)
#define min(a,b) (an2.maxsum;
} node(){}
};node heap[1000010];
int size = 0;
inline int rmq(int l,int r)
}inline void pop()
inline void adjust_up(int l)
}inline void push(node l)
inline int getint()
do res = (res << 1) + (res << 3) + tmp - '0';
while (isdigit(tmp = getchar()));
return sgn ? res : -res;
}int main()
} for (int i=1;i+l-1
#include #include #include #define max(a,b) (a>b?a:b)
#define min(a,b) (aheap;
inline long lg2(ll a)
long rmq(long l,long r)
} for (long i=1;i+l-1
noi2010 超級鋼琴 堆 RMQ
問題描述 小z是乙個小有名氣的鋼琴家,最近c博士送給了小z一架超級鋼琴,小z希望能夠用這架鋼琴創作出世界上最美妙的 這架超級鋼琴可以彈奏出n個音符,編號為1至n。第i個音符的美妙度為ai,其中ai可正可負。乙個 超級和弦 由若干個編號連續的音符組成,包含的音符個數不少於l且不多於r。我們定義超級和弦...
NOI2010 超級鋼琴
傳送門 這個題有趣。巧妙地利用st表和堆 首先最暴力的我就不說了 第二個暴力就是主席樹 堆,預計得分70 80,時間o klog 2n std是用堆儲存可能的區間,然後用st表查詢區間最小值 因為其實如果知道區間右端點,再處理個字首和s 那麼就只要查詢區間最小值就可以了,可以st表o 1 做 inc...
NOI2010 超級鋼琴
求出字首和 對於每個結尾i,設現在取的區間是 j 1,i 則i r j i l,取出該區間sum j 的最小值,將sum i sum j 放入堆中 建立乙個大根堆,每次取出堆頂元素,將排名k 1,將sum i 區間第k小值放入堆中 求區間第k小可以用主席樹 直到取滿k次為止 include incl...