• P3648 [APIO2014]序列分割


    传送门

    首先容易证明,得分和切的顺序没有关系

    所以直接默认先切左边再切右边就好了

    然后显然可以 $dp$

    一开始想的是设 $f[i][j]$ 表示切了 $i$ 次,此次把 $j$ 和 $j+1$ 分开,得到的最大价值

    那么显然枚举上一次切的位置 $k$ ,那么 $f[i][j]=f[i-1][k]+(sum[j]-sum[k])(sum[n]-sum[j])$

    这个东西是可以斜率优化+滚动数组,但是很不好写,一堆边界问题要想,代码就不放了(亲自尝试发现甚至会爆$long long$)

    另一个好的思路:设 $f[i][j]$ 表示已经切了 $i$ 次,只考虑前面 $j$ 块的最大价值

    同样枚举 $k$,$f[i][j]=f[i-1][k]+(sum[i]-sum[j])*sum[j]$

    这样式子就好化了:$f[i][j]=f[i-1][k]+sum[i]sum[j]-sum[j]^2$

            :$-sum[i]sum[j]+f[i][j]=f[i-1][k]-sum[j]^2$

    那么 $k=-sum[i],x=sum[j],b=f[i][j],y=f[i-1][k]-sum[j]^2$

    发现 $k,x$ 都单调,所以直接斜率优化就好了,同样要滚动数组

    注意原序列可能有 $0$,那么 $x$ 就不是单调上升而是单调不增,求斜率时要注意特判 $x$ 相同的情况!

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef long double ldb;
    inline int read()
    {
        register int x=0,f=1; static char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e5+7;
    int n,m;
    ll sum[N],f[2][N];
    inline ll X(int x) { return sum[x]; }
    inline ll Y(int x) { return f[1][x]-sum[x]*sum[x]; }
    inline ldb slope(int i,int j)
    {
        if(X(i)==X(j)) return Y(i)>Y(j) ? -1e18 : 1e18;
        return (ldb)(Y(i)-Y(j))/(X(i)-X(j));
    }
    int Q[N],l,r;
    int main()
    {
        n=read(); m=read();
        register int i,j;
        for(i=1;i<=n;i++) sum[i]=sum[i-1]+read();
        for(j=1;j<=m;j++)
        {
            l=r=1;
            for(i=1;i<=n;i++)
            {
                while(l<r && -sum[i]<=slope(Q[l],Q[l+1]) ) l++;
                int &k=Q[l];
                f[0][i]=f[1][k]+(sum[i]-sum[k])*sum[k];
                while(l<r && slope(Q[r-1],Q[r]) <= slope(Q[r],i) ) r--;
                Q[++r]=i;
            }
            swap(f[0],f[1]);
        }
        printf("%lld
    ",f[1][n]);
        return 0;
    }
  • 相关阅读:
    isNUll ,对于sql中的一个表的description的NULL和空格的处理
    Thread类学习
    java学习计划
    HTTP请求过程(http是一种无状态协议,即不建立持久的连接)
    JS事件流(W3C与IE区别)
    学习Javascript闭包
    div内长串数字或字母不断行处理
    仿购物车加减数字
    多行文字两行断尾点点点显示
    MegaCli命令详解
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10723094.html
Copyright © 2020-2023  润新知