【APIO2014】Split the sequence

\(ProblemLink\)

The meaning of problems

You're playing on a length \ (n \) game non-negative integer sequence. This game you need to sequence into \ (k + 1 \) non-empty blocks. In order to obtain \ (k + 1 \) block, you need to repeat the following operations \ (K \) views:

  1. Selecting a block of more than one element (initially you only one, i.e. the entire sequence)
  2. Select two elements adjacent to this block is parted in the middle to give two non-empty blocks.

After each operation you will get two points newly generated element blocks and of the product. You want to maximize the final total score.

Solution

Obviously each pair \ (i, J \) , if they are not in the same block, will produce \ (a_i * a_j \) contribution.

Apparently \ (\ Large f_ {p, i} = \ max ({f_ {p-1, j}} + s_j (s_i-s_j)) \)

Provided transfer \ (J, k \) , than k J

\(j<k\)

\(\large f_{p-1,j}+(s_j*(s_i-s_j))>f_{p-1,k}+(s_k*(s_i-s_k))\)

\(\large f_{p-1,j}-s_j^2+s_is_j>f_{p-1,k}-s_k^2+s_is_k\)

\(\huge s_i>\frac{f_{p-1,k}- f_{p-1,j}+s_j^2-s_k^2}{s_j-s_k}\)

Directly on the slope can be optimized

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IL inline
#define RG register
#define gi geti<int>()
#define gl geti<ll>()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
template<typename T>
IL T geti()
{
    RG T xi=0;
    RG char ch=gc;
    bool f=0;
    while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
    while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=1e5+7;
int n,k;
ll a[N],f[N][2],s[N];
int pr[N][210],now,pre;
int q[N];
inline ll sqr(ll p){return p*p;}
inline double slope(int j,int k)
{
    if(s[j]==s[k])return -1e18;
    return (f[k][pre]-f[j][pre]+sqr(s[j])-sqr(s[k]))/static_cast<double>(s[j]-s[k]);
}
int main(void)
{
    n=gi,k=gi;
    for(int i=1;i<=n;++i)a[i]=gi,s[i]=s[i-1]+a[i];
    for(int p=1;p<=k;++p)
    {
        q[0]=0;
        int l=0,r=0;    
        now=p&1,pre=now^1;
        for(int i=1;i<=n;++i)
        {
            while(l<r&&slope(q[l],q[l+1])<=s[i])++l;
            int j=q[l];
            f[i][now]=f[j][pre]+(s[i]-s[j])*s[j];
            pr[i][p]=j;
            while(l<r&&slope(q[r],i)<=slope(q[r-1],q[r]))--r;
            q[++r]=i;
        }
    }
    pi(f[n][now],'\n');
    for(int i=k,w=n;i;--i)pi(w=pr[w][i],' ');
    return 0;
}

Guess you like

Origin www.cnblogs.com/LLCSBlog/p/11626960.html