zoukankan      html  css  js  c++  java
  • luogu P2512 [HAOI2008]糖果传递

    传送门

    Time cost: 35min

    环形均分纸牌

    我们再回顾一下均分纸牌

     1     scanf("%d",&n);
     2     for(i = 1; i <= n; i++)
     3     {
     4         scanf("%d",a + i);
     5         sum += a[i];
     6     }
     7     double ave = sum / (double)n;
     8     int tim = n;
     9     sum = 0;
    10     for(int i = 1; i <= n; i++)
    11     {
    12         sum += a[i];
    13         if(sum / (double)i == ave) --tim;
    14     }

    就这么个东西

    数组元素减掉平均值之后求前缀和

    前缀和为0的时候就说明不用从左边移牌到右边 次数-1

    这个题虽然问的是最小传递数 但是效果一样 

    开始可以考虑枚举断开的点

    如果在k点断开 那么就相当于从k开始求前缀和

    但是每遍求前缀和复杂度会爆炸O(n^2)

    所以可以从1开始求的前缀和推出来后面的就是

    n点的前缀和 S[n]-S[k]

    1点的前缀和 S[1]+S[n]-S[k]

    (就写这两个应该就知道了)

    这样就可以O(n^2) 但是还是会爆炸

    然后考虑最后的答案就是所有前缀和求和

    也就是

    考虑数轴上从1到n 每个S[i]位置上有一个点

    求最短距离和

    是不是看到了种树问题?

    所以就取最中间的点就OK

    复杂度O(n)+O(sort)

    Code:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #define rep(i,a,n) for(int i = a;i <= n;++i)
     5 const int N = 1000006;
     6 using namespace std;
     7 typedef long long ll;
     8 ll n,ave,ans;
     9 ll a[N],s[N];
    10 int main() {
    11     scanf("%lld",&n);
    12     rep(i,1,n) scanf("%lld",a+i),ave += a[i];
    13     ave /= n;
    14     rep(i,1,n) a[i] -= ave,s[i] = s[i-1] + a[i];
    15     sort(s+1,s+n+1);
    16     ave = s[n+1 >> 1];
    17     rep(i,1,n) ans += abs(ave - s[i]);
    18     printf("%lld
    ",ans);
    19     return 0;
    20 }
    View Code
    > 别忘了 总有人在等着你
  • 相关阅读:
    JQuery的ajax函数执行失败,alert函数弹框一闪而过
    ThinkPHP5.1中数据查询使用field方法数组参数起别名时遇到的问题
    Linux Web服务器集群搭建
    三层架构之UI层
    Aircoinst 三层架构ASP.NET开源
    [教程]KALI LINUX 2.0 2019 更新国内源
    工厂模式
    Java 实现序列化和反序列化
    Java实现缓冲流 编码 & 解码
    Java使用IO流读取文件显示到控制台2
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9811559.html
Copyright © 2011-2022 走看看