思路是找到第一个最小值的位置作为一次操作的左端点,右端点也可以得到。
这是代码:
#include <bits/stdc++.h>
#define int long long
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid (l + r >> 1)
#define lc ls, l, mid
#define rc rs, mid + 1, r
#define pd pushdown(u, l, r)
#define pu pushup(u)
using namespace std;
const int maxn = 1e5 + 10;
int n, m, l;
int a[maxn];
struct node {
int p, v, tag;
};
node tr[maxn << 2];
void pushup(int u) {
if (tr[ls].v <= tr[rs].v) tr[u].v = tr[ls].v, tr[u].p = tr[ls].p;
else tr[u].v = tr[rs].v, tr[u].p = tr[rs].p;
}
void pushdown(int u, int l, int r) {
if (tr[u].tag) {
tr[ls].tag += tr[u].tag, tr[rs].tag += tr[u].tag;
tr[ls].v += tr[u].tag, tr[rs].v += tr[u].tag;
tr[u].tag = 0;
}
}
void build(int u, int l, int r) {
if (l == r) {
tr[u].p = l, tr[u].v = a[l];
return;
}
build(lc), build(rc), pu;
}
void modify(int u, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) {
++tr[u].tag, ++tr[u].v;
return;
}
pd;
if (ql <= mid) modify(lc, ql, qr);
if (qr > mid) modify(rc, ql, qr);
pu;
}
signed main() {
cin >> n >> m >> l;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (m--) {
int pos = min(tr[1].p, n - l + 1);
modify(1, 1, n, pos, pos + l - 1);
}
cout << tr[1].v << endl;
return 0;
}
证不出来贪心的正确性但是过了。