传送门

算法 : 瞎搞......

这种题是真的恶心....

以下为一堆的结论和证明...

(自己口胡的,比较细,实在不想看也可以直接看结论)


首先如果要让每个人最终的糖果一样多

1.那么肯定最终每个人的糖果数量为 每个人糖果数量的平均数..(显然...)

还有一个显然的结论:

2.如果 a 把糖分给别人,那么 a 就不应该再收到糖

不然就不可能是最优方法(a 还不如少分一点糖给别人,这样糖果的交换数量还更小)

当然反过来也一样。

3.如果 a 的糖果数量大于平均数,那么 a 一定要分糖给别人(由 1. 可得)

并且 a 也不会再接受其他人的糖(由 2. 可得)

反过来也是一样:

如果 a 的糖果数量小于平均数,那么 a 一定要从别人接受糖,并且 a 也不会分给其他人糖。

所以有一种比较好的方法:对于每个人只要把多出来的糖传给下一个就好了

如果是缺少糖就把需求传给别人,让别人把需求传下去,设多的是正数,那么需求就为负数,如果负数被抵消了就说明有正数把需求"填满"了,相当于有多出来的糖返回给缺少的人了....(这里可能需要一点网络流反向边的思想...)。

(但是网络流是不可能的,数据太大,直接凉了)

设第 i 个人 原本的糖果数量为 a[ i ],第 i 个人原本的糖果数量减去平均数量 为 b[ i ],(b[ i ] 可能为负数,表示 i 需要 abs( b[ i ] ) 个糖)

那么最终就是要经过转移让所有的 b 都为 0 。

先考虑第一个人 k 怎么分(因为是环形,所以每个人都可以是第一个人)

由 3. 可得,要分 b[ k ] 个糖

那要怎么分(可以左边给几个,右边给几个,也可以只给一边)

方案太多不好搞

但是要注意:4.分给两边其实相当于一边的某一个点把多出来的全部分给另一边....

怎么描述呢:

  就是说 k 分给左边几个糖,分着分着,分到点 j 分完了,剩下的分给右边,最后分到 j 肯定也刚好分平均(由 1. 易证得)

  那就相当于点 j 把要分的的糖全部分给右边

怎么抽象地证明呢:

  自己动手,丰衣足食...
  也不难,k 分给左边几个糖,分到 j 没了,说明 j 是有需求的

  相当于 j 带着需求跑到 k ,这时 j 的需求也刚好没了,然后 k 少了几个糖,把剩下的糖往另一边分

  也就相当于 j 带着全部需求跑了一圈,跑完就分完了

所以由4.可知

我们只需要判断每个点把(需求 or 盈余)只往一边分需要多少糖

对于第一个点 k 要分b[ k ] 个,则对于 k+1 要分 b[k+1]+b[ k ],......,对于 k+m 则要分 b[ k,k+1,...,k+m] 个

那要怎么快速计算这种东西呢

前缀和...

先预处理出 1 到 n 的前缀和,为sum

对于前面的式子,可以化为 abs(sum[ k ]-sum[ k-1 ]),abs(sum[ k+1 ]-sum[ k-1 ]),...,abs(sum[ k+m ]-sum[ k-1 ])

那要怎么选取 k-1 才能使之和最小呢

稍微转换一下:

把每个sum都放到数轴上,则前面的式子就是某个点 k-1 到所有其他点的距离之和

怎么找最小的和那就是“货仓选址”问题了

好吧讲了这么多终于可以发代码了......

代码难度为0.....

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
}
int n;
int a[1000007],b[1000007];
long long ans,tot;
long long sum[1000007];
int main()
{n=read();for(int i=1;i<=n;i++)a[i]=read(),tot+=a[i];tot/=n;for(int i=1;i<=n;i++)b[i]=a[i]-tot;for(int i=1;i<=n;i++)sum[i]=sum[i-1]+b[i];sort(sum+1,sum+n+1);tot=sum[(n+1)/2];for(int i=1;i<=n;i++)ans+=abs(tot-sum[i]);cout<<ans;return 0;
}

转载于:https://www.cnblogs.com/LLTYYC/p/9537513.html

P2512 [HAOI2008]糖果传递相关推荐

  1. luogu P2512 [HAOI2008]糖果传递

    传送门 Time cost: 35min 环形均分纸牌 我们再回顾一下均分纸牌 1 scanf("%d",&n); 2 for(i = 1; i <= n; i++) ...

  2. bz10451045: [HAOI2008] 糖果传递

    1045: [HAOI2008] 糖果传递 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2958  Solved: 1319 [Submit][S ...

  3. bzoj 1045: [HAOI2008]糖果传递

    1045: [HAOI2008] 糖果传递 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4094  Solved: 1970 [Submit][S ...

  4. 【BZOJ】1045: [HAOI2008]糖果传递(中位数)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1045 白书上有讲 没ac的坑点在,数据范围n<=1,000,000 #include < ...

  5. BZOJ1045 HAOI2008糖果传递(贪心)

    显然最后每个小朋友所拥有的糖果数就是糖果数总和的平均数.设该平均数为t. 环的问题一般断成链,但这个题似乎没有什么很好的办法在枚举断点的时候快速算出答案(我甚至不知道会不会有断点) 于是我们假装把他断 ...

  6. BZOJ 1045 [HAOI2008]糖果传递 ★(环形等分:中位数)

    题意 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. 思路 假设平均数是x,且a1给an了k个(k<0说明是an给a1了-k个),那么总代价就 ...

  7. [HAOI2008]糖果传递 结论题

    题目描述 有\(n(n<1000000)\)个小朋友坐成一圈,每人有\(a_i\)个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为\(1\),求使所有人糖果数相等的最小代价. 暴力 ...

  8. [BZOJ1045][HAOI2008] 糖果传递(数学相关)

    题目描述 传送门 题目大意:有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1.求使所有人获得均等糖果的最小代价. 题解 设第i个人会给第i+1个人 xi ...

  9. bzoj1045: [HAOI2008] 糖果传递

    挺有趣的.观察题目环形?切掉一个跑贪心?O(n^2)超时了... 先计算m为每个最终糖果数量. 设An传给A1了k个糖果, 那么A1传给A2的糖果数为S1=k+A1-m,T1=A1-m 那么A2传给A ...

最新文章

  1. 数学分析高等代数考研试题荟萃[更新至2017年10月1日]
  2. Javascript中的对象和原型(一)(转载)
  3. 2020年智能家居市场规模将达到3576亿元
  4. 全国高等学校计算机等级考试(江西考区)一级笔试试卷a,全国高等学校计算机等级考试(江西考区)一级笔试试卷A...
  5. 【C++】随机函数的使用
  6. 小波、超小波(多尺度几何分析)与压缩感知
  7. [渝粤教育] 西南科技大学 计算机辅助设计 在线考试复习资料2021版
  8. 「leetcode」106.从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树 (详解)
  9. 关于日期控件被模态框遮盖的问题解析
  10. 札记:android手势识别,MotionEvent
  11. 交换机路由器常用命令
  12. Python雷电小游戏、战机小游戏源代码源程序
  13. javascript中的二维数组定义
  14. 优秀的程序员是没有性生活的
  15. Android Studio制作简易音乐盒
  16. win7休眠设置在哪里_win7怎么开启休眠模式
  17. Navicat12.0.29_Premium_cs_x64激活
  18. 企业工商信息查询第三方软件/API查询原理分析
  19. android 对话框 美化,Android修改Dialog样式
  20. natapp实现内网穿透(详解)

热门文章

  1. 安卓非常实用的自动化测试工具 -- Monkey详细的说明
  2. windows 搜索文件
  3. 网络安全之tcp阻截引擎 (一)
  4. c++如何使用json配置文件
  5. c语言生日创意代码_用C语言写个代码,利用空格和符号拼写出生日快乐之类的...
  6. 第k大的数python代码_Python实现查找数组中任意第k大的数字算法示例
  7. 北斗轨迹记录_跑步GPS轨迹经常“飘”?要是用咱们的北斗,会好吗...
  8. php案例分析百度云_百度阅读|助力推动阅读领域无障碍优化(二)
  9. docker-compose 配置kafka_Docker Compose 引用环境变量
  10. 【ElasticSearch】IK分词加入标点符号