杂题训练之九

https://www.luogu.org/problem/P2048

昨天和大佬们一起复习了

见此题不错,于是写一篇题解

题目大意:

求长度在[L,R]的范围的子串和前K大和

分析:

考虑暴力一点,把所有满足条件的字串加入一个堆中

取的前K次就是前k大

发现这样不太好

这样的瓶颈在于要考虑所以字串(包括那些不太有用的)

具体实现:

对于区间[L,R],题目要求使得字串和最大,且长度也要在其之间

考虑中间有个点mid,它是MAX{sum[mid]-sum[L-1]}
这样再将[L,mid-1]和[mid+1,R]压入堆中

其中找mid要用RMQ

又因为区间[L,R]可以平移所以考虑一个三维组(i,i+L-1,i+R-1)

保证这样一定不会算漏

code:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXN 500005
#define LOG 20
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
long long sum[MAXN], table[MAXN][LOG];
namespace RMQ {
    void init(int n) {
        for (int i = 1; i <= n; i++) table[i][0] = i;
        for (int j = 1; (1 << j) <= n; j++)
            for (int i = 1; i + (1 << j) - 1 <= n; i++) {
                int x = table[i][j - 1], y = table[i + (1 << (j - 1))][j - 1];
                table[i][j] = sum[x] > sum[y] ? x : y;
            }
    }
    int query(int l, int r) {
        int k = log2(r - l + 1);
        int x = table[l][k], y = table[r - (1 << k) + 1][k];
        return sum[x] > sum[y] ? x : y;
    }
}
struct element {
    int o, l, r, t;
    element() {}
    element(int o, int l, int r) : o(o), l(l), r(r), t(RMQ::query(l, r)) {}
    friend bool operator < (const element& a, const element& b) {
        return sum[a.t] - sum[a.o - 1] < sum[b.t] - sum[b.o - 1];
    }
};
std::priority_queue< element > Q;
int main() {
    int n, k, L, R;
    scanf("%d%d%d%d", &n, &k, &L, &R);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &sum[i]);
        sum[i] += sum[i - 1];
    }
    RMQ::init(n);
    for (int i = 1; i <= n; i++)
        if (i + L - 1 <= n) 
            Q.push(element(i, i + L - 1, min(i + R - 1, n)));
    long long ans = 0;
    while (k--) {
        int o = Q.top().o, l = Q.top().l, r = Q.top().r, t = Q.top().t;
        Q.pop();
        ans += sum[t] - sum[o - 1];
        if (l != t) Q.push(element(o, l, t - 1)); 
        if (t != r) Q.push(element(o, t + 1, r));
    }
    printf("%lld
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wzxbeliever/p/11738233.html