BZOJ3675: [Apio2014]序列分割

來源:互聯網
上載者:User

標籤:int   開始   ring   while   scanf   傳送門   turn   algorithm   http   

【傳送門:BZOJ3675】簡要題意:

  一開始給出n個數的一段序列,可以分割k次,每次只能分割一段序列,一段序列被分割後就變成兩個序列,每次分割的價值為分割的位置左邊的數的和乘右邊的數的和

  求出最大價值

題解:

  DP+斜率最佳化

  首先來設f[i][k]為前i個數,分割k次得到的最大價值

  接下來。。。

  方程。。。。

  方程。。。

  方程。。

  方程。

  需要玄學思考

  假設一段序列為4|1 2|3(|表示分割)

  那麼f[2][1]=4*1=4

  f[4][2]=4*(1+2+3)+(1+2)*3=f[2][1]+(4+1)*(3+2)!!

  其實這裡用了乘法分配律

  太棒了這樣就得到f[i][k]=max(f[j][k-1]+sum[j]*(sum[i]-sum[j]))

  然後滾動數組f[i][now]=max(f[j][last]+sum[j]*(sum[i]-sum[j]))

  再用斜率最佳化,美滋滋

  設j1<j2<i

  得到

  f[j2][last]+sum[j2]*(sum[i]-sum[j2])>f[j1][last]+sum[j1]*(sum[i]-sum[j1])

  f[j2][last]-f[j1][last]+sum[j1]^2-sum[j2]^2>(sum[j1]-sum[j2])*sum[i]

  (f[j2][last]-f[j1][last]+sum[j1]^2-sum[j2]^2)/(sum[j1]-sum[j2])<sum[i]

  因為sum[j1]-sum[j2]有可能等於0,所以在處理隊列的時候,如果存在sum[j1]-sum[j2],要將j1給除掉,保留j2

  注意加long long

參考代碼:
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;typedef long long LL;//f[i][now]=max(f[j][last]+sum[j]*(sum[i]-sum[j]))//j1<j2<i//f[j2][last]+sum[j2]*(sum[i]-sum[j2])>f[j1][last]+sum[j1]*(sum[i]-sum[j1])//f[j2][last]-f[j1][last]+sum[j1]^2-sum[j2]^2>(sum[j1]-sum[j2])*sum[i]//(f[j2][last]-f[j1][last]+sum[j1]^2-sum[j2]^2)/(sum[j1]-sum[j2])<sum[i]LL f[110000][2];LL sum[110000];int now=1,last=0;LL slop(int j1,int j2){    return (f[j2][last]-f[j1][last]-sum[j2]*sum[j2]+sum[j1]*sum[j1])/(sum[j1]-sum[j2]);}int list[110000];int main(){    int n,K;    scanf("%d%d",&n,&K);    sum[0]=0;    for(int i=1;i<=n;i++)    {        int d;        scanf("%d",&d);        sum[i]=sum[i-1]+d;    }    memset(f,0,sizeof(f));    for(int k=1;k<=K;k++)    {        now^=1;last^=1;        int head=1,tail=0;list[head]=0;        for(int i=k;i<=n;i++)        {            while(head<tail&&(sum[list[head]]==sum[list[head]+1]||slop(list[head],list[head+1])<sum[i])) head++;            int j=list[head];            f[i][now]=f[j][last]+sum[j]*(sum[i]-sum[j]);            while(head<tail&&(sum[i]==sum[list[tail]]||slop(list[tail-1],list[tail])>slop(list[tail],i))) tail--;            list[++tail]=i;        }    }    printf("%lld\n",f[n][now]);    return 0;}
 

BZOJ3675: [Apio2014]序列分割

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.