st turn save location (worth) + greedy (luoguP2048 [NOI2010] super piano

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

The meaning of problems

To a sequence A, a large output of the previous subinterval and k and

n , k <= 500000

-1000 ≤ Ai ≤ 1000.1 ≤ L ≤ R ≤ n

analysis

After reading clear title it is easy to think of violence, and to count with the prefix and range, the intervals and join the heap, and then remove before adding to k

But this will MLE, super memory

Look again questions, think about your own violence, we know that with the first o notes to the left point, there are many legitimate sub-interval, it will MLE, but the topic is seeking the maximum range of a few and so we get a greedy strategy: each addition heap o is left is the optimal point, which is the maximum interval and, instead of the whole added to the list, so you do not the MLE.

Definition of triple (o, l, r) = max (sum [t] - sum [o-1] | t∈ [l, r]), (o, l, r) expressed in the left end point o, right point [l, r] interval and maximum values ​​within the range, because the sum [o-1] is constant, so we need only sum [t] to the maximum, the maximum static --RMQ.

However, we think again greedy strategy're wrong . While it can not be selected from t optimum position, but there may be suboptimal, the first k large, and the interval: (o, l, t- 1) and (o, t + 1, r ), in order to avoid repetitive and does not lose other better solution (the solution is to ensure accurate and complete) , we still want to (O, L, t - 1) ( O , L, t-1), which go back into the pile. Obviously, before discharge back should guarantee the existence range, i.e., where l = t r = t or Japanese sentence to be performed.

Here the (O, L, t - 1), ( O , t + 1, r) will throw a pile of operation is a clear need to maintain our position, and the table is saved in st value, we need to move about the brain, the st things changed in the maintenance position. This operation is taken out (o, l, r) then do, because they do not (o, l, r) excellent, and such a position after the maintenance is convenient

#include<cstdio>
#include<queue>
using namespace std;
#define MAX 500000
#define ll long long

int sum[MAX], f[MAX][19];
int n,k, l, r;

void st() {
    for(int k = 1; (1<<k) <= n; k++) 
        for(int i = 1; i+(1<<k)-1 <= n; i++) {
            int x = f[i][k-1] , y = f[i + (1<<(k-1))][k-1];
            f[i][k] = sum[x] > sum[y] ? x : y;
        }
}

int RMQ(int l, int r) {
    int k = 0;
    while(1<<(k+1) <= r-l+1) k++;
    int x = f[l][k], y = f[r-(1<<k)+1][k];
    return sum[x] > sum[y] ? x : y;
}

struct node{
    int o, l, r, t;
    node(int o = 0, int l = 0, int r = 0) : o(o), l(l), r(r), t(RMQ(l, r)) {} 
    bool operator < (const node& xxx) const {
        return sum[t]-sum[o-1] < sum[xxx.t]-sum[xxx.o-1];
    }
};
priority_queue <node> q;

int main() {
    scanf("%d%d%d%d", &n,&k,&l,&r);
    for(int i = 1; i <= n; i++) {
        scanf("%d",&sum[i]);
        f[i][0] = i;
        sum[i] += sum[i-1];
    }
    st();
    for(int i = 1; i <= n; i++) 
        if(i+l-1 <= n) q.push(node(i, i+l-1, min(i+r-1, n) )) ;
    ll ans = 0;
    int o, l, r, t;
    for(int i = 1; i <= k; i++) {
        o = q.top().o, l = q.top().l, r = q.top().r, t = q.top().t;
        q.pop() ;
        ans += (ll)(sum[t]-sum[o-1]);
        if (l != t) q.push(node(o, l, t - 1)); 
        if (t != r) q.push(node(o, t + 1, r));
    }
    printf("%lld", ans);
}

Guess you like

Origin www.cnblogs.com/tyner/p/11256977.html