Description
小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐。
这架超级钢琴可以弹奏出n个音符,编号为1至n。第i个音符的美妙度为Ai,其中Ai可正可负。
一个“超级和弦”由若干个编号连续的音符组成,包含的音符个数不少于L且不多于R。我们定义超级和弦的美妙度为其包含的所有音符的美妙度之和。两个超级和弦被认为是相同的,当且仅当这两个超级和弦所包含的音符集合是相同的。
小Z决定创作一首由k个超级和弦组成的乐曲,为了使得乐曲更加动听,小Z要求该乐曲由k个不同的超级和弦组成。我们定义一首乐曲的美妙度为其所包含的所有超级和弦的美妙度之和。小Z想知道他能够创作出来的乐曲美妙度最大值是多少。
Solution
设一个四元组(i,l,r,t)表示当前以i为左端点,[l,r]一定为可行的区间的子集,t表示[l,r]最大前缀和的下标。维护一个堆,对于堆顶元素,贡献完答案后,插入 (i,l,t−1,query(l,t−1)) ( i , l , t − 1 , q u e r y ( l , t − 1 ) ) 和 (i,t+1,r,query(t+1,r)) ( i , t + 1 , r , q u e r y ( t + 1 , r ) ) 。可以用st表来维护。
Source
啥?用了make_heap
卡常还比肖大佬跑得慢,果然自带大常数。。。
/************************************************
* Au: Hany01
* Date: Mar 2nd, 2018
* Prob: [BZOJ2006][NOI2010] 超级钢琴
* Email: hany01@foxmail.com
************************************************/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define fir first
#define sec second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia
template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
inline int read()
{
register int _, __; register char c_;
for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
return _ * __;
}
inline void File()
{
#ifdef hany01
freopen("bzoj2006.in", "r", stdin);
freopen("bzoj2006.out", "w", stdout);
#endif
}
const int maxn = 500005, maxlog = 20;
int n, k, L, R, Log2[maxn], f[maxn][maxlog], Sum[maxn];
struct Item
{
int st, l, r, ed;
Item(int st = 0, int l = 0, int r = 0, int ed = 0): st(st), l(l), r(r), ed(ed) {}
bool operator < (const Item& item) const {
return Sum[ed] - Sum[st - 1] < Sum[item.ed] - Sum[item.st - 1];
}
};
inline void Init()
{
n = read(), k = read(), L = read(), R = read(), Log2[0] = -1;
For(i, 1, n) Sum[i] = Sum[i - 1] + read(), Log2[i] = Log2[i >> 1] + 1, f[i][0] = i;
For(i, 1, Log2[n]) For(j, 1, n - (1 << i) + 1)
if (Sum[f[j][i - 1]] > Sum[f[j + (1 << (i - 1))][i - 1]]) f[j][i] = f[j][i - 1]; else f[j][i] = f[j + (1 << (i - 1))][i - 1];
}
inline int query(int l, int r) {
int tmp = Log2[r - l + 1];
if (Sum[f[l][tmp]] > Sum[f[r - (1 << tmp) + 1][tmp]]) return f[l][tmp]; else return f[r - (1 << tmp) + 1][tmp];
}
inline void Solve()
{
static Item q[maxn * 3], top;
static int l, r, cnt = 0;
static LL Ans = 0;
For(i, 1, n) {
l = i + L - 1, r = min(i + R - 1, n);
if (l <= r) q[cnt ++] = Item(i, l, r, query(l, r));
}
make_heap(q, q + cnt);
while (k --) {
top = q[0], Ans += Sum[top.ed] - Sum[top.st - 1], pop_heap(q, q + cnt --);
l = top.l, r = top.ed - 1;
if (l <= r) q[cnt ++] = Item(top.st, l, r, query(l, r)), push_heap(q, q + cnt);
l = top.ed + 1, r = top.r;
if (l <= r) q[cnt ++] = Item(top.st, l, r, query(l, r)), push_heap(q, q + cnt);
}
printf("%lld\n", Ans);
}
int main()
{
File();
Init();
Solve();
return 0;
}