Description
小Z是一個小有名氣的鋼琴家,最近C博士送給了小Z一架超級鋼琴,小Z希望能夠用這架鋼琴創作出世界上最美妙的音樂。 這架超級鋼琴可以彈奏出 n 個音符,編號爲 1 至 n。第i個音符的美妙度爲 Ai,其中 Ai 可正可負。 一個“超級和絃”由若干個編號連續的音符組成,包含的音符個數不少於 L 且不多於 R。我們定義超級和絃的美妙度爲其包含的所有音符的美妙度之和。兩個超級和絃被認爲是相同的,當且僅當這兩個超級和絃所包含的音符集合是相同的。 小Z決定創作一首由 k 個超級和絃組成的樂曲,爲了使得樂曲更加動聽,小Z要求該樂曲由 k 個不同的超級和絃組成。
我們定義一首樂曲的美妙度爲其所包含的所有超級和絃的美妙度之和。小Z想知道他能夠創作出來的樂曲美妙度最
大值是多少。
Input
第一行包含四個正整數 n, k, L, R。其中 n 爲音符的個數,k 爲樂曲所包含的超級和絃個數,L和R分別是超級和絃所包含音符個數的下限和上限。 接下來 n 行,每行包含一個整數 Ai ,表示按編號從小到大每個音符的美妙度。
Output
只有一個整數,表示樂曲美妙度的最大值。
Sample Input
4 3 2 3
3
2
-6
8
Sample Output
11
[樣例說明]
共有5種不同的超級和絃:
音符1 ~ 2,美妙度爲3 + 2 = 5
音符2 ~ 3,美妙度爲2 + (-6) = -4
音符3 ~ 4,美妙度爲(-6) + 8 = 2
音符1 ~ 3,美妙度爲3 + 2 + (-6) = -1
音符2 ~ 4,美妙度爲2 + (-6) + 8 = 4
最優方案爲:樂曲由和絃1,和絃3,和絃5組成,美妙度爲5 + 2 + 4 = 11。
HINT
N <= 500,000,k <= 500,000
-1000 <= Ai <= 1000, 1 <= L <= R<= N且保證一定存在滿足條件的樂曲
Solution :
這道題需要找到子區間第
現在考慮找到第
Code :
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#include <queue>
#define LL long long
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int MAXN = 5e5 + 5;
int a[MAXN], pre[MAXN], n, k, Log[MAXN], mx[20][MAXN];
LL ans;
struct point {
int l, r, i, val, pos;
point() {}
point(int _l, int _r, int _i, int _val, int _pos) : l(_l), r(_r), i(_i), val(_val), pos(_pos) {}
bool operator < (const point & a) const {
return val < a.val;
}
};
inline int new_max(int x, int y) {
return pre[x] > pre[y] ? x : y;
}
inline void ST() {
Log[0] = -1;
for(int i = 1; i <= n; ++i) Log[i] = Log[i >> 1] + 1;
for(int i = 1; i <= n; ++i) mx[0][i] = i;
for(int j = 1; (1 << j) <= n; ++j)
for(int i = 1; i + (1 << j) - 1 <= n; ++i)
mx[j][i] = new_max(mx[j - 1][i], mx[j - 1][i + (1 << j - 1)]);
}
inline int find(int l, int r) {
int k = Log[r - l + 1];
return new_max(mx[k][l], mx[k][r - (1 << k) + 1]);
}
priority_queue<point> q;
inline void wr(LL x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) wr(x / 10);
putchar(x % 10 + '0');
}
int main() {
n = read(), k = read(); int L = read(), R = read();
for(int i = 1; i <= n; ++i) a[i] = read(), pre[i] = pre[i - 1] + a[i];
ST();
for(int i = 1; i <= n; ++i)
if(i + L - 1 <= n) {
int ls = i + L - 1, rs = min(i + R - 1, n);
int pos = find(ls, rs), val = pre[pos] - pre[i - 1];
q.push(point(ls, rs, i, val, pos));
}
else break;
while(!q.empty() && k) {
--k;
point now = q.top(); q.pop();
ans += now.val;
point ls = now, rs = now;
ls.r = now.pos - 1;
if(ls.r >= ls.l)
ls.pos = find(ls.l, ls.r), ls.val = pre[ls.pos] - pre[ls.i - 1], q.push(ls);
rs.l = now.pos + 1;
if(rs.r >= rs.l)
rs.pos = find(rs.l, rs.r), rs.val = pre[rs.pos] - pre[rs.i - 1], q.push(rs);
}
wr(ans);
}