博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二分 前缀和 借教室 洛谷P1083
阅读量:5162 次
发布时间:2019-06-13

本文共 1274 字,大约阅读时间需要 4 分钟。

题目链接:

题意:一共有n天,每天可提供Ri个教室,有m份订单,每份订单是从第Si天到第Ji天,借Di个教室,问是否能借完。

分析:一开始想着用线段树,但是线段树在区间更新的时候并不是一个个更新,而是将一整个区间的值改变,对应的点想要查询时再将lazy标记下放,用线段树会非常慢,故不用线段树。

 这里有一篇非常好的博客:

在这里提炼下内容:

差分是前缀和数组的逆运算

前缀和是用元数据求元与元之间的并集关系,而差分则是根据元与元之间的逻辑关系求元数据,是互逆思想

是否能二分的界定标准是:状态的决策过程或者序列是否满足单调性或者可以局部舍弃性。 而在这个题里,因为如果前一份订单都不满足,那么之后的所有订单都不用继续考虑;而如果后一份订单都满足,那么之前的所有订单一定都可以满足,符合局部舍弃性,所以可以二分订单数量。(不太好懂,看代码就能理解)

注意:need数组是独立于rest数组的,diff数组是服务于need数组的,diff[i]数组是need[i]-need[i-1],我们利用差分方便的进行修改,最后求出need数组与rest数组做比较(不要轻易相减以防出现re)

#include
using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;//这个数是1e9数量级的,且可以用memset函数 const int maxn=1e6+7;const double pi=acos(-1);const int mod=1e9+7;int rest[maxn],d[maxn],l[maxn],r[maxn],diff[maxn],need[maxn];int n,m;bool isok(int x){
//用来判断前x份订单需不需要进行修改 memset(diff,0,sizeof(diff)); for(int i=1;i<=x;i++){ diff[l[i]]+=d[i]; diff[r[i]+1]-=d[i]; } for(int i=1;i<=n;i++){ need[i]=need[i-1]+diff[i]; if(need[i]>rest[i]){ return 0; } } return 1;}int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&rest[i]); } for(int i=1;i<=m;i++){ scanf("%d%d%d",&d[i],&l[i],&r[i]); } if(isok(m)){cout<<0<

 

转载于:https://www.cnblogs.com/qingjiuling/p/11217025.html

你可能感兴趣的文章
B/S和C/S架构的区别
查看>>
[Java] Java record
查看>>
jQuery - 控制元素显示、隐藏、切换、滑动的方法
查看>>
postgresql学习文档
查看>>
Struts2返回JSON数据的具体应用范例
查看>>
js深度克隆对象、数组
查看>>
socket阻塞与非阻塞,同步与异步
查看>>
团队工作第二天
查看>>
System类
查看>>
tableView
查看>>
Happy Great BG-卡精度
查看>>
Xamarin Visual Studio不识别JDK路径
查看>>
菜鸟“抄程序”之道
查看>>
Ubuntu下关闭防火墙
查看>>
TCP/IP 邮件的原理
查看>>
原型设计工具
查看>>
windows下的C++ socket服务器(4)
查看>>
css3 2d转换3d转换以及动画的知识点汇总
查看>>
【Java】使用Eclipse进行远程调试,Linux下开启远程调试
查看>>
对Vue为什么不支持IE8的解释之一
查看>>