CF949D Curfew

原题链接

大致题意:现在寝室要熄灯了,宿管开始查寝,但是许多同学们还待在朋友的寝室里。现在已知这一层楼有nn个寝室排成一排,每个寝室住有bb个人,而现在每个寝室分别有a1,a2,a3,…,an{a_1,a_2,a_3,\dots,a_n}个人,1号宿管从1号寝室往nn号寝室方向查各个寝室人数,2号宿管从nn号寝室往1号寝室查各个寝室人数,两个宿管各自负责检查一半的寝室里的人数,当nn为奇数的时候,1号宿管负责(n+1)/2(n+1)/2号寝室。由于宿管想快点检查完寝室,他们只检查每个寝室里的人数是否是bb个人,而不管是哪bb个人。而机智的同学们可以趁着宿管检查某一个寝室的时候躲起来避免被宿管计入到该寝室的人数,也可以移动dd个寝室的距离,到另一个寝室里。但是宿管会在检查完一个寝室后把该寝室锁住,里面的人出不来,外面的人也进不去。假设1号宿管检查出有xx个寝室里的人数不等于bb,2号宿管检查出有yy个寝室里的人数不等于bb,则第二天老师的生气程度和max(x,y)max(x,y)成正相关,所以请问最好情况下,max(x,y)max(x,y)的最小值是多少。

解法:考虑只有1号宿管的情况下,对于该宿管即将检查的ii号寝室,如果无论如何都无法使得这个寝室的人数不少于b个人,即∑i∗(d+1)j=iaj<b{\sum_{j=i} ^{i*(d+1)}a_j \lt b },则不如让这个寝室全部移动到i+1{i+1}号寝室里,让后面的寝室人数更加容易达到b,即使得后续局面更优。

反之,如果可以通过移动使得第ii个寝室的人数达到b,即∑i∗(d+1)j=iaj≥b{\sum_{j=i} ^{i*(d+1)}a_j \ge b },那么与其让这bb个人聚集在后面的寝室,不如直接聚集到ii号寝室来得到一个合格的寝室。

具体做法是,先求一个数组aa的前缀和数组sumsum,同时维护一个resres余量,表示从前面的寝室移动来的人数减去前面的合格寝室里的人的数量,那么贪心策略下当前ii号寝室合格的充要条件就是sum[min(n,i∗(d+1))]−sum[i−1]+res≥b{sum[min(n,i*(d+1))]-sum[i-1]+res \ge b},然后只需要O(n)的时间复杂度就可以统计出合格的寝室数量。

那么如果有两个宿管的时候呢?首先有个显然的结论,如果让前(n+1)/2{(n+1)/2}个寝室执行上述贪心策略,则可以使得1号宿管检查的合格寝室数量达到最多,对于2号宿管也也有一样的结论。那么考虑最优化下的结果,就是使得max(x,y)max(x,y)取得最小值时的策略,不妨假设x>y{x \gt y},那么对于前(n+1)/2{(n+1)/2}个寝室,如果通过上述贪心策略来使前(n+1)/2{(n+1)/2}个寝室的合格寝室数量增加1,那么可能会对后n/2n/2个寝室产生影响,然而最坏只会使后n/2n/2个寝室里合格的寝室数量减一,并不会使max(x,y)max(x,y)变得更差,于是max(x,y)max(x,y)此时就是前(n+1)/2{(n+1)/2}个寝室的贪心策略下的不合格数量。

同样的在x<y{x \lt y}的情况下也有相似的结论。

于是最终的答案就是max(前(n+1)/2个寝室的贪心策略下的不合格数量,后n/2个寝室的贪心策略下的不合格数量){max(前(n+1)/2个寝室的贪心策略下的不合格数量,后n/2个寝室的贪心策略下的不合格数量)}

代码如下:

#include<bits/stdc++.h>
#define MAXN 510000
#define MAXM 1020000
using namespace std;typedef long long LL;inline void read(int &x){char ch;bool flag=false;for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());x=flag?-x:x;
}inline void read(long long &x){char ch;bool flag=false;for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());x=flag?-x:x;
}inline void write(long long x){static const int maxlen=100;static char s[maxlen];if (x<0) {   putchar('-'); x=-x;}if(!x){ putchar('0'); return; }int len=0; for(;x;x/=10) s[len++]=x % 10+'0';for(int i=len-1;i>=0;--i) putchar(s[i]);
}int n,len,aim;
int a[ MAXN ];
int tmp[ MAXN ];
int pre[ MAXN ];int main(){read(n); read(len); read(aim);for (int i=1;i<=n;i++){read(a[i]);tmp[i]=a[i];a[i]+=a[i-1];}int res=0;int ans=0;for (int i=1;i<=(n+1)/2;i++){if ( a[min(n*1ll, 1ll*i*(len+1))]-a[i-1]+res>= aim ){res-=aim;ans++;}res+=a[i]-a[i-1];}int MAX=(n+1)/2-ans;res=0;reverse(tmp+1,tmp+n+1);for(int i=1;i<=n;i++)a[i]=tmp[i],a[i]+=a[i-1];ans=0;for (int i=1;i<=n/2;i++){if ( a[min(n*1ll, 1ll*i*(len+1))]-a[i-1]+res>= aim ){res-=aim;ans++;}res+=a[i]-a[i-1];}MAX=max(MAX , n/2-ans);printf("%d\n",MAX);return 0;
}

CF949D Curfew 贪心相关推荐

  1. 【CF949D】Curfew(贪心)

    [CF949D]Curfew(贪心) 题面 CF 洛谷 破池姐姐翻译好强啊 题解 今天菊开讲这题,我大力猜想一波说肯定从中间有个分界线,他还说可能是假的 大力贪心就好了,从两边往中间考虑,只要这个房间 ...

  2. 算法设计与分析第3章 贪心算法

    第4章 贪心算法 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 贪心算法的基本要素 1.贪心选择性质 所谓贪心选择性质是指所 ...

  3. 贪心算法单源点最短路径例题c语言源代码,Dijkstra算法是解单源最短路径问题的一个贪心算法...

    问题描述 给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数. 另外,还给定 V 中的一个项点,称为源. 现在我们要计算从源到所有其他各项点的最短路径长度. 这里的长度是指路上各边权之 ...

  4. Too Many Segments CF595D 贪心乱搞

    传送门! 比赛的时候没有时间写了,看看了看大佬的代码,学习学习. 一开始实验室大佬说是用差分写的,但是看了代码发现打cf的人大家都是stl狂魔! 贪心思路:区间按照左端点排序,从1~2e5遍历每一个点 ...

  5. Roundgod and Milk Tea 贪心

    这个题好像可以用一种类似与置换的贪心方法来做~ sum记为剩余奶茶,一开始sum等于奶茶和 ans记录已经喝的奶茶数 不用排序,我们就从前往后直接处理,考虑的是每一个班最多可以喝多少杯奶茶 就是从剩余 ...

  6. 贪心算法简单实践 -- 分糖果、钱币找零、最多区间覆盖、哈夫曼编解码

    1. 贪心算法概览 贪心算法是一种算法思想.希望能够满足限制的情况下将期望值最大化.比如:Huffman编码,Dijkstra单源最短路径问题,Kruskal最小生成树 等问题都希望满足限制的情况下用 ...

  7. 贪心:expedition 最优加油方法

    已知一条公路上,有一个起点与一个终点,这之间有n个加油站;已知从这n个加 油站到终点的距离d与各个加油站可以加油的量l,起点位置至终点的距离L与起 始时刻油箱中汽油量P;假设使用1个单位的汽油即走1个 ...

  8. 贪心:Burst Balloons 最少次数完成射击气球

    已知在一个平面上有一定数量的气球,平面可以看作一个坐标系,在平面的x轴的不同位 置安排弓箭手向y轴方向射箭,弓箭可以向y轴走无穷远;给定气球的宽度 xstart ≤ x ≤ xend,问至少需要多少弓 ...

  9. 贪心:jump 游戏(获取最少跳跃的次数以及跳跃路径)

    一个数组存储了非负整型数据,数组中的第i个元素a[i],代表了可以从数组第i个 位置最多向前跳跃a[i]步;已知数组各元素的情况下,求是否可以从数组的第0个位置跳跃到数组的最后一个元素的位置,返回最少 ...

  10. 贪心:Jump Game 跳跃游戏

    一个数组存储了非负整型数据,数组中的第i个元素a[i],代表了可以从数组第i个 位置最多向前跳跃a[i]步;已知数组各元素的情况下,求是否可以从数组的第0个位置跳跃到数组的最后一个元素的位置,返回是t ...

最新文章

  1. Burrard 大桥
  2. HTML和XHTML的区别
  3. 小技巧:Chrome开发者工具里的Alt+单击
  4. Linux进阶之路————磁盘查询
  5. Win7上Git安装及配置过程 [转]
  6. 【Elasticsearch】为什么我在Elasticsearch集群中看到大量的拒绝?
  7. canvas中文显示乱码 html5_40个常见的HTML5 面试问题及答案
  8. Java面向对象之构造方法模拟捕鱼达人游戏【附源码】
  9. Matlab Tricks(九)—— 矩阵行/列的增广(删除)
  10. Linux-iptables初识
  11. ES6的新特性(9)——对象的扩展
  12. sourceforge.net居然被劫持??
  13. iOS 手势UIGestureRecognizer详解
  14. 利用pdfminer3k 使用python语言提取PDF中的文本
  15. 老虎证券爬取港股(对小米股价的实时显示和报警)
  16. 神马笔记 版本1.3.0
  17. 7-78 求e的近似值 (15 分)
  18. 《Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks》论文翻译
  19. 最优化方法一:微分求极值
  20. java抽象方法声明_java抽象类和抽象方法

热门文章

  1. vue 富文本编辑器提取纯文字
  2. Pocket PC访问PC上的Webservice
  3. MT9255无法使用mm指令编译某个模块的问题
  4. vs 应用程序无法正常启动0xc000007b 可能与VS中DLL引用有关
  5. iPhone入门学习汇总
  6. 设计模式_访问者模式
  7. 正面管教读书笔记 10 你的性格对孩子性格的影响
  8. mysql 存储过程 if !=_mysql 存储过程 if !=
  9. win8、server 2012 清除winsxs文件夹
  10. 贰贰许远东在浙江省社科联学术年会上关于“中小企业数字化之路”的分享