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

    4518: [Sdoi2016]征途

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 1125  Solved: 623
    [Submit][Status][Discuss]

    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

    m^2乘进去。
    S=((X-x1)^2+(X-x2)^2+......+(X-xm)^2)*m
      =m(m*X^2-2*X*(x1+x2+...+xm)+(x1^2+x2^2+...+xm^2))
      =m(x1^2+x2^2+...+xm^2)-(x1+x2+x3+...+xm)^2
    观察这个式子,只需要求得(x1^2+x2^2+...+xm^2)的最小值就可以了。
    f[i][j]代表走到i天,走了j段路的最小代价,
    f[i][j]=max(f[i-1][k]+(s[j]-s[k])^2)
    s[j]代表前缀和。初值f[0][0]=0
    明显可以斜率优化。
     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #define maxn 3010
     8 #define LL long long 
     9 using namespace std;
    10 LL s[maxn],f[maxn][maxn],q[maxn];
    11 bool getx(int i,int x1,int x2,int x3){
    12   return (-s[x2]*s[x2]-f[i-1][x2]+s[x1]*s[x1]+f[i-1][x1])*(2*s[x2]-2*s[x3])>
    13     (-s[x3]*s[x3]-f[i-1][x3]+s[x2]*s[x2]+f[i-1][x2])*(2*s[x1]-2*s[x2]);
    14 }
    15 LL getans(int i,int j,int k){
    16   return -2*s[j]*s[k]+s[k]*s[k]+f[i-1][k]+s[j]*s[j];
    17 }
    18 int main()
    19 {
    20   freopen("menci_journey.in","r",stdin);
    21   freopen("menci_journey.out","w",stdout);
    22   int n,m;
    23   scanf("%d%d",&n,&m);
    24   for(int i=1;i<=n;i++)
    25     scanf("%lld",&s[i]),s[i]+=s[i-1];
    26   memset(f,127,sizeof(f));
    27   f[0][0]=0;
    28   for(int i=1;i<=m;i++){
    29     int head=0,tail=1;
    30     for(int j=1;j<=n;j++){
    31       while(head+2<=tail && getx(i,q[tail-2],q[tail-1],q[tail]))
    32     q[tail-1]=q[tail],tail--;
    33       while(head<tail && getans(i,j,q[head])>=getans(i,j,q[head+1])) head++;
    34       f[i][j]=getans(i,j,q[head]);
    35       q[++tail]=j;
    36     }
    37   }
    38   /*for(int i=1;i<=m;i++)
    39     for(int j=1;j<=n;j++)
    40       for(int k=0;k<=j;k++)
    41     f[i][j]=min(f[i][j],f[i-1][k]+(s[j]-s[k])*(s[j]-s[k]));*/
    42   printf("%lld",f[m][n]*m-s[n]*s[n]);
    43   return 0;
    44 }
  • 相关阅读:
    NOIP2018游记
    NOIP2018T1DAY1——Road(并查集做法??)
    UVA11021 Tribles——概率dp
    捡石头——(期望递推)
    USACO2008mar-gold牛跑步(第k短路:A-star)
    Java中的异常处理
    Java学习手册
    各种应用层注入手段整理 【转载】
    正则表达式学习
    Run-Time Check Failure #0,The value of ESP was not properly saved 错误解决
  • 原文地址:https://www.cnblogs.com/pantakill/p/6708395.html
Copyright © 2011-2022 走看看