zoukankan      html  css  js  c++  java
  • 征途 BZOJ 4518

    征途

    【问题描述】

    Pine开始了从S地到T地的征途。

    从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。

    Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。

    Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。

    帮助Pine求出最小方差是多少。

    设方差是v,可以证明,v×m^2是一个整数。为了避免精度误差,输出结果时输出v×m^2。

    【输入格式】

    第一行两个数 n、m。

    第二行 n 个数,表示 n 段路的长度

    【输出格式】

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

    【样例输入】

    5 2
    1 2 5 8 6

    【样例输出】

    36

    【数据范围】

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


    题解:

    来推一下式子:

    方差:(x1 - aver)2 + (x2 - aver)+ ... + (xm - aver)2  / m

    然后题意要求乘m2

    那么

     m×[(x1 - aver)2 + (x2 - aver)+ ... + (xm - aver)]

    = m×[x12 + x22 + ... + xm2 - 2aver(x+ x2 + ... + xm ) + m × aver2]

    = m×(x12 + x22 + ... + xm2) - 2sum+ sum2  (aver = sum / m)

    = m×(x12 + x22 + ... + xm2) - sum

    其实m和sum都为常量,那么只要考虑中间的平方和部分

    设f[i][j]为分到点j且分成i段时每一段的平方和

    转移方程即为:f[i][j] = min(f[i][j], f[i - 1][k] + (sum[j] - sum[k]) * (sum[j] - sum[k])); (k < j)

    三方效率肯定过不了,看出这是一个斜率优化的裸题,那就可以虾搞蛋了~(≧▽≦)/~

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<cstdio>
     6 #include<cmath>
     7 using namespace std;
     8 inline int Get()
     9 {
    10     int x = 0;
    11     char c = getchar();
    12     while('0' > c || c > '9') c = getchar();
    13     while('0' <= c && c <= '9')
    14     {
    15         x = (x << 3) + (x << 1) + c - '0';
    16         c = getchar();
    17     }
    18     return x;
    19 }
    20 int n, m;
    21 int t, w;
    22 int c[10233];
    23 int s[10233];
    24 long long aver;
    25 long long f[3233][3233];
    26 long long sum[10233];
    27 double Up(int x, int y, int i)
    28 {
    29     return f[i - 1][x] + sum[x] * sum[x] - f[i - 1][y] - sum[y] * sum[y];
    30 }
    31 double Down(int x, int y)
    32 {
    33     return (sum[x] - sum[y]) << 1;
    34 }
    35 long long Dp(int i, int j, int x)
    36 {
    37     return f[i - 1][x] + (sum[j] - sum[x]) * (sum[j] - sum[x]);
    38 }
    39 int main()
    40 {
    41     scanf("%d%d", &n, &m);
    42     for(int i = 1; i <= m; ++i)
    43         for(int j = 1; j <= n; ++j)
    44             f[i][j] = 214748364721474836LL;
    45     for(int i = 1; i <= n; ++i)
    46     {
    47         scanf("%d", &c[i]);
    48         sum[i] = sum[i - 1] + c[i];
    49         f[1][i] = sum[i] * sum[i];
    50     }
    51     aver = sum[n];
    52     for(int i = 2; i <= m; ++i)
    53     {
    54         t = 1, w = 0;
    55         s[++w] = i - 1;
    56         for(int j = i; j <= n; ++j)
    57         {
    58 /*            
    59             for(int k = i - 1; k <= j; ++k)
    60             f[i][j] = min(f[i][j], f[i - 1][k] + (sum[j] - sum[k]) * (sum[j] - sum[k]));
    61 */
    62             while(t < w && Up(s[t], s[t + 1], i) / Down(s[t], s[t + 1]) <= sum[j]) ++t;
    63             f[i][j] = Dp(i, j, s[t]);
    64             while(t < w && Up(j, s[w], i) / Down(j, s[w]) <= Up(s[w], s[w - 1], i) / Down(s[w], s[w - 1])) --w;
    65             s[++w] = j;
    66         }
    67     }
    68     printf("%lld", (long long) m * f[m][n] - aver * aver);
    69 }
  • 相关阅读:
    mac c++编译出现segmentation fault :11错误
    ssh 连接缓慢解决方法
    237. Delete Node in a Linked List
    203. Remove Linked List Elements
    Inversion of Control Containers and the Dependency Injection pattern
    82. Remove Duplicates from Sorted List II
    83. Remove Duplicates from Sorted List
    SxsTrace
    使用CCleaner卸载chrome
    decimal and double ToString problem
  • 原文地址:https://www.cnblogs.com/lytccc/p/6248001.html
Copyright © 2011-2022 走看看