• [SDOI2016]征途


    [SDOI2016]征途

    题目

    思路

    这题目很绕(其实也还好)。
    首先让我们看看要求的到底是什么。

    [ans=m^2 imes s^2(s^2为方差) ]

    定义(v)为每一段的平均数,(b_i)为第(i)段的长度,(sum)为路径总长。
    所以

    [s^2=frac{1}{m}sum_{i=1}^m(b_i-v)^2 ]

    [ans=msum_{i=1}^m(b_i-v)^2 ]

    完全平方式展开

    [ans=msum_{i=1}^m(b_i^2-2b_iv+v^2) ]

    拆掉(sum)

    [ans=m(mv^2-2vsum_{i=1}^mb_i+sum_{i=1}^mb_i^2) ]

    因为(mv=sum且sum_{i=1}^mb_i=sum)所以

    [ans=msum_{i=1}^mb_i^2-sum^2 ]

    由于(sum和m)都是已知的,所以我们要做的其实就是把这个序列分成(m)段,使得每一段的和的平方和最小。
    然后可以(DP),设(f[i][j])表示前(i)条路划分为(m)段的最优解,也就是最小平方和。
    然后对路径统计前缀和,(a[i])表示前(i)条路的总长。
    显然(f[i][j]=max{f[k][j-1]+(a[i]-a[k])^2}(k<i))
    这个转移是(O(n^3))的,显然是跑不出来的。
    然后我们会发现,这个可以用斜率优化啊。
    若决策(s_2优于s_1(s_1<s_2))
    当且仅当(f[s_1][j-1]+(a[i]-a[s_1])^2>=f[s_2][j-1]+(a[i]-a[s_2])^2)
    乱搞一波化简就会得到
    若有

    [a[i]>=frac{f[s_1][j-1]+a[s_1]^2-f[s_2][j-1]-a[s_2]^2}{2(a[s_1]-a[s_2])}(s_1<s_2) ]

    那么决策(s_2优于s_1)
    显然(a[i])是单调递增的,所以我们用单调队列维护一个单调递增的斜率即可。不会的戳我

    完整代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int _=3e3+20;
    ll f[_][_],a[_];
    int q[_];
    double slope(int x,int y,int k){
        return (double)((double)f[x][k]+a[x]*a[x]-f[y][k]-a[y]*a[y])/(a[x]-a[y])/2;
    }
    int main(){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;++i){
            scanf("%lld",&a[i]);
            a[i]+=a[i-1];
        }
        for(int i=1;i<=n;++i){
            f[i][1]=a[i]*a[i];
        }
        for(int j=2;j<=m;++j){
            int head=1,tail=1;
            q[1]=j-1;
            for(int i=j;i<=n;++i){
                while(a[i]>=slope(q[head],q[head+1],j-1)&&head<tail)head++;
                int k=q[head];
                f[i][j]=f[k][j-1]+(a[i]-a[k])*(a[i]-a[k]);
                while(slope(q[tail-1],q[tail],j-1)>=slope(q[tail],i,j-1)&&tail>head)tail--;
                q[++tail]=i;
            }
        }
        cout<<f[n][m]*m-a[n]*a[n]<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    linux less命令用法
    Spark-RDD 模型 以及运行原理
    Spark 架构原理介绍 以及 job、task、stag 概念
    Kafka 基本概念以及框架介绍
    负载均衡- TCP/ IP 基础知识
    JAVA多线程和并发基础面试题
    Java并发使用--线程池
    Java基础--并发编程
    事务实现原则(一) 事务的改变以及JDBC事务的设计
    Spark RDD Transformation和Action
  • 原文地址:https://www.cnblogs.com/ljq-despair/p/8810311.html
Copyright © 2020-2023  润新知