APIO2014Split the sequence

Posted llcsblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了APIO2014Split the sequence相关的知识,希望对你有一定的参考价值。

\(ProblemLink\)

题意

你正在玩一个关于长度为\(n\)的非负整数序列的游戏。这个游戏中你需要把序列分成 \(k+1\) 个非空的块。为了得到 \(k+1\)块,你需要重复下面的操作\(k\)次:

  1. 选择一个有超过一个元素的块(初始时你只有一块,即整个序列)
  2. 选择两个相邻元素把这个块从中间分开,得到两个非空的块。

每次操作后你将获得那两个新产生的块的元素和的乘积的分数。你想要最大化最后的总得分。

Solution

显然每一对\(i, j\), 如果它们不在同一个块中, 就会产生 \(a_i*a_j\) 的贡献.

显然有\(\Large f_p,i=\max(f_p-1,j+s_j(s_i-s_j))\)

设转移\(j,k\),j优于k

\(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>\fracf_p-1,k- f_p-1,j+s_j^2-s_k^2s_j-s_k\)

直接上斜率优化即可

#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;

以上是关于APIO2014Split the sequence的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 1059E. Split the Tree

HDU 5783 Divide the Sequence

842.Split Array into Fibonacci Sequence

LeetCode 842. Split Array into Fibonacci Sequence

842. Split Array into Fibonacci Sequence —— weekly contest 86

[Apio2014]序列分割