[luoguP2048/NOI2010] 超级钢琴

原题链接

sol

所求为连续值之和,因此先计算前缀和 \(s\),那么固定左端点 \(i\) 后,最大的连续和即为 \(-s_{i-1} + \max_{j=i + l - 1}^{\min\{i+r-1,n\}} s_j\),使用 ST 表即可计算出最大区间和。由于该左端点仍有可能对答案产生贡献,因此在取走某个答案后,需要将其长度范围分为两半,可以需要使用堆来动态解决。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;
typedef long long LL;

const int N = 500005, K = 19;

int n, k, l, r;
int a[N], s[N];
int st[N][K + 1], pos[N][K + 1];
int lg2[N];

struct Node {
    int u, l, r, k;
    bool operator< (const Node &W) const {
        return s[k] - s[u - 1] < s[W.k] - s[W.u - 1];
    }
};

void init(){
    for (int i = 1; i <= n; i ++ )
        st[i][0] = s[i], pos[i][0] = i;

    for (int i = 2; i <= n; i ++ ) lg2[i] = lg2[i >> 1] + 1;
    
    for (int k = 1; k <= K; k ++ ) {
        for (int l = 1; l + (1 << k) - 1 <= n; l ++ ) {
            int posr = l + (1 << k - 1);
            if (st[l][k - 1] >= st[posr][k - 1]) 
                st[l][k] = st[l][k - 1], pos[l][k] = pos[l][k - 1];
            else 
                st[l][k] = st[posr][k - 1], pos[l][k] = pos[posr][k - 1];
        }
    }
}

int get_max(int l, int r){
    int len = r - l + 1;
    if (st[l][lg2[len]] >= st[r - (1 << lg2[len]) + 1][lg2[len]])
        return pos[l][lg2[len]];
    else
        return pos[r - (1 << lg2[len]) + 1][lg2[len]];
}

int main(){
    scanf("%d%d%d%d", &n, &k, &l, &r);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]), s[i] = s[i - 1] + a[i];
    init();
    
    priority_queue<Node> heap;
    for (int i = 1; i + l - 1 <= n; i ++ ) heap.push({i, l, min(r, n - i + 1), get_max(i + l - 1, min(n, i + r - 1))});

    LL res = 0;
    while (k -- ) {
        Node t = heap.top();
        heap.pop();
        res += s[t.k] - s[t.u - 1];
        int len = t.k - t.u + 1;
        if (len != t.l) heap.push({t.u, t.l, len - 1, get_max(t.u + t.l - 1, t.u + len - 2)});
        if (len != t.r) heap.push({t.u, len + 1, t.r, get_max(t.u + len, t.u + t.r - 1)});
    }
    printf("%lld\n", res);
}
posted @ 2025-04-26 15:12  是一只小蒟蒻呀  阅读(21)  评论(0)    收藏  举报