Cut the Sequence

POJ

The meaning of problems: Given a length of N ( \ (N <= 10. 5 ^ \) ) of the sequence A, which requires the sequence into segments, to meet the "all numbers in each segment, and" no more than M ( \ ( M <= 10 ^ {11} \) premise), so that "maximum value of all numbers in each segment," the minimum. minimum value is obtained.

Analysis: Let \ (F [i] \) represents the front into segments and the number i satisfies the minimum condition.

\(f[i]=min_{0<=j<i,\sum_{k=j+1}^iA_k<=m}f[j]+max_{j+1<=k<=i}A_k\)

Binary \ (nlogn \) pretreated for each a i, satisfies \ (\ sum_ {k = j + 1} ^ iA_k <= m \) the minimum value of j, referred to as \ (C [I] \) .

For \ (max_ {j + 1 < = k <= i} A_k \) using monotone queue optimization.

Handle more than two can be directly transferred \ (f [i] = f [c [i]] + a [q [l]] \)

How to calculate \ (max_ {j + 1 <= K <= I} a_k \) ? There are two ways, one ST, two monotonous nature of the queue with the present problem, the queue an item \ (max_ {j + 1 <= k <= i} a_k \) is the value of the next element a queue (a method is easy to prove difficult to write, I out for half an hour, or WA;. method II card, but do not know easy to write one line of code).

Remember to open long long ...

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define LL long long
using namespace std;
inline LL read(){
    LL s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
const int N=100005;
LL a[N],c[N],q[N],f[N],sum[N];
int main(){
    LL n=read(),m=read();int bj=1;
    for(int i=1;i<=n;i++){
        a[i]=read();
        if(a[i]>m)bj=0;
        sum[i]=sum[i-1]+a[i];
    }
    if(!bj){puts("-1");return 0;}
    for(int i=1;i<=n;i++){
        int l=1,r=i,mid,cnt;
        while(l<=r){
            mid=(l+r)>>1;
            if(sum[i]-sum[mid-1]<=m)cnt=mid,r=mid-1;
            else l=mid+1;
        }
        c[i]=cnt-1;
    }
    int l=1,r=0;
    for(int i=1;i<=n;i++){
        while(l<=r&&a[q[r]]<=a[i])r--;
        q[++r]=i;
        while(l<=r&&q[l]<=c[i])l++;
        f[i]=f[c[i]]+a[q[l]];
        for(int j=l;j<=r;j++){
            f[i]=min(f[i],f[q[j]]+a[q[j+1]]);
        }
    }
    printf("%lld\n",f[n]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/PPXppx/p/10958822.html
cut