zoukankan      html  css  js  c++  java
  • 【BZOJ】【3675】【APIO2014】序列分割

    DP+斜率优化


      首先我们根据这个分割的过程可以发现:总得分等于k+1段两两的乘积的和(乘法分配律),也就是说与分割顺序是无关的。

      再对乘积进行重分组(还是乘法分配律)我们可以转化为:$ans=sum$第 i 段×前 i-1 段的和

      所以我们就可以以分割次数为阶段进行DP啦~

      令f[i][j]表示将前 j 个数分成 i 段的最大得分,那么就有$$f[i][j]=max{ f[i-1][k]+sum[k]×(sum[j]-sum[k]) }$$我们观察到这个式子其实是很像斜率优化的……而且sum明显满足单调性!所以来推一下决策单调性的式子=。=

      当决策k1<k2时:

      $$ egin{aligned} f[i-1][k1]+sum[k1]*(sum[j]-sum[k1]) &< f[i-1][k2]+sum[k2]*(sum[j]-sum[k2]) \ sum[j]*(sum[k1]-sum[k2]) &< f[i-1][k2]-f[i-1][k1]+sum[k1]^2-sum[k2]^2 \ sum[j] &> frac{f[i-1][k2]-f[i-1][k1]+sum[k1]^2-sum[k2]^2}{sum[k1]-sum[k2]} end{aligned}$$

      这题我被坑在:$sum[k1]-sum[k2]leq 0$!!!

      所以搞斜率的时候,分母可能为0……所以就不能写成斜率的形式,而是搞成上一行那种……但是由于有个负数,所以还要仔细考虑不等号的方向!QAQ

     1 /**************************************************************
     2     Problem: 3675
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:18176 ms
     7     Memory:5180 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 3675
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 inline int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 const int N=1e5+10,INF=~0u>>2;
    29 typedef long long LL;
    30 /******************tamplate*********************/
    31 LL f[2][N],a[N],sum[N];
    32 int from[N],n,m,q[N];
    33 double slope(int i,int j,int k){
    34     i=i&1;
    35     return double(f[i][k]-f[i][j]+sum[j]*sum[j]-sum[k]*sum[k]);
    36 }
    37 int main(){
    38 #ifndef ONLINE_JUDGE
    39     freopen("3675.in","r",stdin);
    40     freopen("3675.out","w",stdout);
    41 #endif
    42     n=getint(); m=getint();
    43     F(i,1,n) a[i]=getint(),sum[i]=sum[i-1]+a[i];
    44     F(i,1,m){
    45         int now=i&1;
    46         int l=0,r=-1; q[0]=0;
    47         F(j,1,n){
    48             while(l<r && slope(i-1,q[l],q[l+1])>=sum[j]*(sum[q[l]]-sum[q[l+1]])) l++;
    49             int t=q[l];
    50             f[now][j]=f[now^1][t]+sum[t]*(sum[j]-sum[t]);
    51             while(l<r && slope(i-1,q[r-1],q[r])*(sum[q[r]]-sum[j])>=slope(i-1,q[r],j)*(sum[q[r-1]]-sum[q[r]])) r--;
    52             q[++r]=j;
    53         }
    54     }
    55     printf("%lld
    ",f[m&1][n]);
    56     return 0;
    57 }
    View Code

    3675: [Apio2014]序列分割

    Time Limit: 40 Sec  Memory Limit: 128 MB
    Submit: 541  Solved: 202
    [Submit][Status][Discuss]

    Description

    小H最近迷上了一个分割序列的游戏。在这个游戏里,小H需要将一个长
    度为N的非负整数序列分割成k+l个非空的子序列。为了得到k+l个子序列,
    小H将重复进行七次以下的步骤:
    1.小H首先选择一个长度超过1的序列(一开始小H只有一个长度为n的
    序列一一也就是一开始得到的整个序列);
    2.选择一个位置,并通过这个位置将这个序列分割成连续的两个非空的新
    序列。
    每次进行上述步骤之后,小H将会得到一定的分数。这个分数为两个新序
    列中元素和的乘积。小H希望选择一种最佳的分割方案,使得k轮(次)之后,
    小H的总得分最大。

    Input

    输入文件的第一行包含两个整数n和尼(k+1≤n)。
    第二行包含n个非负整数a1,n2….,an(0≤ai≤10^4),表示一开始小H得
    到的序列。

    Output


    一行包含一个整数,为小H可以得到的最大得分。

    Sample Input

    7 3
    4 1 3 4 0 2 3

    Sample Output

    108

    HINT



    【样例说明】

    在样例中,小H可以通过如下3轮操作得到108分:

    1.-开始小H有一个序列(4,1,3,4,0,2,3)。小H选择在第1个数之后的位置

    将序列分成两部分,并得到4×(1+3+4+0+2+3)=52分。

    2.这一轮开始时小H有两个序列:(4),(1,3,4,0,2,3)。小H选择在第3个数

    字之后的位置将第二个序列分成两部分,并得到(1+3)×(4+0+2+

    3)=36分。

    3.这一轮开始时小H有三个序列:(4),(1,3),(4,0,2,3)。小H选择在第5个

    数字之后的位置将第三个序列分成两部分,并得到(4+0)×(2+3)=

    20分。

    经过上述三轮操作,小H将会得到四个子序列:(4),(1,3),(4,0),(2,3)并总共得到52+36+20=108分。

    【数据规模与评分】

    :数据满足2≤n≤100000,1≤k≤min(n -1,200)。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    POJ 1811 Prime Test 素性测试 分解素因子
    sysbench的安装与使用
    电脑中已有VS2005和VS2010安装.NET3.5失败的解决方案
    I.MX6 show battery states in commandLine
    RPi 2B Raspbian system install
    I.MX6 bq27441 driver porting
    I.MX6 隐藏电池图标
    I.MX6 Power off register hacking
    I.MX6 Goodix GT9xx touchscreen driver porting
    busybox filesystem httpd php-5.5.31 sqlite3 webserver
  • 原文地址:https://www.cnblogs.com/Tunix/p/4458648.html
Copyright © 2011-2022 走看看