P2048 [NOI2010] 超级钢琴 RMQ + Heap
妙妙妙。
我们可以考虑先求出一些区间的最优解 \((s, t, l, r, w)\) 表示 \([l, r]\) 的最优解为 \([s, t]\) 值为 \(w\).
再考虑将 \((s, maxpos(l, t - 1), l, r, sum[maxpos(l, t - 1)] - sum[s - 1])\) 和 \((s, maxpos(t + 1,r), l, r, sum[maxpos(t + 1, r)] - sum[s - 1])\) 插入堆中, 最后取 \(k\) 个即可.
CODE :
// Cutslo 's CODE
// ST - RMQ
// 2022 - 3 - 31
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#define int long long
using namespace std;
inline int read () {
int ans = 0; char c = getchar(), last = ' ';
while(c < '0' || c > '9') last = c,c = getchar();
while(c >= '0' && c <= '9') ans = (ans << 1) + (ans << 3) + c - '0',c = getchar();
return last == '-' ? - ans : ans;
}
const int N = 5e5 + 10;
int n, k, l, r, ans, sum[N], st[N][22];
struct NODE {
int s, t, l, r;
bool operator < (const NODE & x) const { return sum[t] - sum[s - 1] < sum[x.t] - sum[x.s - 1]; }
};
priority_queue <NODE> que;
inline void Init () {
for (int i = 1; i <= n; i ++) st[i][0] = i;
int t = (int)log2(n);
for (int j = 1; j <= t; j ++)
for (int i = 1; i + (1 << j) <= n + 1; i ++) {
int p = st[i][j - 1], q = st[i + (1 << (j - 1))][j - 1];
st[i][j] = sum[p] > sum[q] ? p : q;
}
}
inline int query (int l, int r) {
int t = (int)log2(r - l + 1), p = st[l][t], q = st[r - (1 << t) + 1][t];
return sum[p] > sum[q] ? p : q;
}
signed main () {
n = read(), k = read(), l = read(), r = read();
for (int i = 1; i <= n; i ++) sum[i] = read() + sum[i - 1];
Init();
for (int i = 1; i <= n; i ++) {
int p = i + l - 1, q = min(i + r - 1, n);
if (p <= n) que.push(NODE{i, query(p, q), p, q});
}
for (int i = 1; i <= k; i ++) {
NODE st = que.top();
int s = st.s, t = st.t, l = st.l, r = st.r;
que.pop(), ans += sum[t] - sum[s - 1];
if (l != t) que.push(NODE{s, query(l, t - 1), l, t - 1});
if (r != t) que.push(NODE{s, query(t + 1, r), t + 1, r});
}
cout << ans;
return 0;
}
启发很大。
登高自卑,行远自迩。

浙公网安备 33010602011771号