此题不需要二分,直接线段树维护贪心,为什么是对的
查看原帖
此题不需要二分,直接线段树维护贪心,为什么是对的
362750
TernaryTree楼主2023/4/15 17:59

思路是找到第一个最小值的位置作为一次操作的左端点,右端点也可以得到。

这是代码:

#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;
}

证不出来贪心的正确性但是过了。

2023/4/15 17:59
加载中...