zoukankan      html  css  js  c++  java
  • BZOJ4518: [Sdoi2016]征途

    Description

    Pine开始了从S地到T地的征途。
    从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。
    Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。
    Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。
    帮助Pine求出最小方差是多少。
    设方差是v,可以证明,v×m^2是一个整数。为了避免精度误差,输出结果时输出v×m^2。
     

    Input

    第一行两个数 n、m。
    第二行 n 个数,表示 n 段路的长度
     

    Output

     一个数,最小方差乘以 m^2 后的值

     

    Sample Input

    5 2
    1 2 5 8 6

    Sample Output

    36

    HINT

    1≤n≤3000,保证从 S 到 T 的总路程不超过 30000

     
    方差:s^2=Σ(Ai-x)^2/m
    全都乘一个m^2,然后就是斜率优化丝帛题,设f[i][j]表示前j天,现在到了第i段路的最小方差。
    S[i]表示前缀和*m,x表示所有数之和。
    f[i][j]=min{f[i`][j-1]+(S[i]-S[i`]-x)^2}
    倒腾一下式子
    f[i][j]=(S[i]-x)^2+ min{(f[i`][j-1]+S[i`]^2)-(2*S[i`])*(S[i]-x)}
                                                    y                       x               k
    可以看成一条直线在y轴上截距,维护一个下凸壳即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=3010;
    const ll inf=1ll<<60;
    ll f[2][maxn],S[maxn];
    int n,m,x,cur,Q[maxn];
    double slop(int x,int y) {return (double)(f[cur^1][x]+S[x]*S[x]-f[cur^1][y]-S[y]*S[y])/(2*S[x]-2*S[y]);}
    ll getdp(int k,int i) {return f[cur^1][k]+S[k]*S[k]-2*S[k]*(S[i]-x);}
    int main() {
    	n=read();m=read();
    	rep(i,1,n) S[i]=S[i-1]+read()*m;
    	x=S[n]/m;
    	rep(i,1,n) f[0][i]=inf;
    	rep(j,1,m) {
    		cur^=1;int l=1,r=0;
    		rep(i,j,n) {
    			while(l<r&&slop(Q[r-1],Q[r])>=slop(Q[r],i-1)) r--;Q[++r]=i-1;
    			while(l<r&&getdp(Q[l],i)>=getdp(Q[l+1],i)) l++;
    			f[cur][i]=getdp(Q[l],i)+(S[i]-x)*(S[i]-x);
    		}
    	}
    	printf("%lld
    ",f[cur][n]/m);
    	return 0;
    }
    

      

  • 相关阅读:
    【codeforces 785B】Anton and Classes
    【codeforces 785C】Anton and Fairy Tale
    【t003】string
    【BZOJ 1028】[JSOI2007]麻将
    【t011】最小覆盖子串
    【BZOJ 1029】[JSOI2007]建筑抢修
    cgb2008-京淘day02
    抽象类与接口概念及代码实例
    【hihocoder 1296】数论三·约瑟夫问题
    【hihocoder 1295】Eular质数筛法
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5486476.html
Copyright © 2011-2022 走看看