zoukankan      html  css  js  c++  java
  • bzoj 3675 [Apio2014]序列分割(斜率DP)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=3675

    【题意】

        将n个数的序列分割k次,每次的利益为分割后两部分数值和的积,求最大利益。

    【思路】

        设f[i][j]表示将前i个分割j次的最大获益,则有转移式:

            f[i][j]=max{ f[k][j-1]+(S(i)-S(k))*S(k) }

        设a<b,若b决策优于a决策则有:

            (S[b]^2-S[a]^2+f[a][j-1]-f[b][j-1])/(S[b]-S[a])<S[i]

        单调队列维护下凸包,每次保持队首的最优性,维护队尾的下凸性。队列中的点至少要有一个。

    【代码】

     1 #include<set>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
    10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    11 using namespace std;
    12 
    13 typedef long long ll;
    14 const int N = 2e5+10;
    15 
    16 ll read() {
    17     char c=getchar();
    18     ll f=1,x=0;
    19     while(!isdigit(c)) {
    20         if(c=='-') f=-1; c=getchar();
    21     }
    22     while(isdigit(c))
    23         x=x*10+c-'0',c=getchar();
    24     return x*f;
    25 }
    26 
    27 int n,K,tot;
    28 ll f[N][2],cur,q[N],qh,qt,a[N],S[N];
    29 /*
    30 double slop(ll a,ll b) {
    31     return (double)(S[b]*S[b]-S[a]*S[a]+f[a][cur^1]-f[b][cur^1])/(double)(S[b]-S[a]);
    32 }
    33 */
    34 ll up(ll a,ll b) 
    35 {
    36     return (S[b]*S[b]-S[a]*S[a]+f[a][cur^1]-f[b][cur^1]);
    37 }
    38 ll down(ll a,ll b) 
    39 {
    40     return (S[b]-S[a]);
    41 }
    42 
    43 int main()
    44 {
    45     n=read(),K=read();
    46     FOR(i,1,n) {
    47         a[++tot]=read();
    48         if(!a[tot]) --tot;
    49     }
    50     n=tot;
    51     FOR(i,1,n) S[i]=S[i-1]+a[i];
    52     FOR(round,1,K) {
    53         cur^=1;
    54         qh=1; qt=0;
    55         FOR(i,round,n) {
    56             while(qh<qt&up(q[qh],q[qh+1])<S[i]*down(q[qh],q[qh+1])) qh++;
    57             int t=q[qh];
    58             f[i][cur]=f[t][cur^1]+(S[i]-S[t])*S[t];
    59             while(qh<qt&&up(q[qt-1],q[qt])*down(q[qt-1],i)>up(q[qt-1],i)*down(q[qt-1],q[qt])) qt--;
    60             q[++qt]=i;
    61         }
    62     }
    63     printf("%lld
    ",f[n][cur]);
    64     return 0;
    65 }
  • 相关阅读:
    手机端html滑动处理
    css控制div上下移动
    倒计时javascript
    PHP解决抢购等阻塞式高并发redis处理思路
    jQuery判断当前元素是第几个元素
    CSS 实现盒子水平居中、垂直居中和水平垂直居中的方法
    yii1.* session无法调用问题
    百度小程序坑坑坑
    php等比缩放图片
    lavarel的小失误
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5296455.html
Copyright © 2011-2022 走看看