【wikioi】1217 借教室
题目链接http://www.wikioi.com/problem/1217/
算法:二分答案(线段树可过wikioi数据)
- 二分:http://www.wikioi.com/solution/list/1217/ (我不多阐述)
不难看出这道题满足二分条件 所以我们对数据进行二分
维护一个具有前缀和性质的数组sum记录当前二分区间内的教室需求情况,那么第i天需要的教室数为∑sum(1→i)。
维护方法:若订单i是从si天到ti天要借di个教室,那么sum[si]+=di,sum[ti+1]-=di。
计算每天的需求量是否超出教室量,如果有,答案必定在该区间,继续二分该区间,否则答案应该在另一个区间,继续二分。
(如果答案是0,一直二分下去肯定会有l = r的情况,然后就跳出来了=-=,此时m = l - 1)
丧心病狂の加速:如果不是二分区间内的而且没读入的数据,你读它什么呢?233
(这样写的好处有:①比线段树代码短②比线段树速度快 >_<)
我的代码
#include <cstdio>
using namespace std; #define MID (l+r) >> 1 const int maxn = 1000000+10;
int sum[maxn], cl[maxn], d[maxn], s[maxn], t[maxn], n, m, last, last_q; int check(int r) {
int ret = 0;
for(int i = 1; i <= n; ++i) { //这里必须要到n,因为是用前缀和, 即sum[t[i]]的t[i]后可能还有sum= =。。
ret += sum[i];
if(ret > cl[i]) return 0;
}
return 1;
} int main() {
scanf("%d%d", &n, &m);
int l = 1, r = m, mid, i;
for(i = 1; i <= n; ++i) scanf("%d", &cl[i]);
while(l <= r) {
mid = MID;
if(last_q < mid){
for(i = last+1; i <= mid; ++i) scanf("%d%d%d", &d[i], &s[i], &t[i]);
last_q = mid;
}
//这里最容易错,要清楚标记
for(i = mid+1; i <= last; ++i) sum[s[i]] -= d[i], sum[t[i]+1] += d[i]; //将原来加上去的和减的恢复
for(i = last+1; i <= mid; ++i) sum[s[i]] += d[i], sum[t[i]+1] -= d[i]; //加上去的和减去新添加的元素
last = mid;
if(check(mid)) l = mid+1;
else r = mid-1;
}
//一般闭区间二分的答案是l-1,在这里,l-1=m时说明所有人都满足
if(l-1 == m) printf("0");
else printf("-1\n%d", l); //而因为l-1是答案,所以l-1+1=l就是下一个不符合答案的
return 0;
} - 线段树(区间更新和维护最小)
注意:用线段树最容易错的地方就是认为当修改后全部教室加起来的和为负的那个人就是解。其实应该是每天的教室需求量,不是和。所以不能维护区间和,要维护一个最小值,最小值为负,说明这个人就是答案
#include <cstdio>
using namespace std; #define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define MID (l+r)>>1
#define lc rt << 1
#define rc rt << 1 | 1 int min(const int& a, const int& b){return a < b ? a : b;} const int maxn = 1e6+10;
int minx[maxn << 2], add[maxn << 2], n, m, L, R, _add; //向上传递最小的
void pushup(int rt) {
minx[rt] = min(minx[lc], minx[rc]);
} //向下传递修改值
void pushdown(int rt) {
if(add[rt]) {
add[lc] += add[rt];
add[rc] += add[rt];
minx[lc] += add[rt];
minx[rc] += add[rt];
add[rt] = 0;
}
} void build(int l, int r, int rt) {
add[rt] = 0;
if(l == r) {
scanf("%d", &minx[rt]);
return;
}
int m = MID;
build(lson); build(rson);
pushup(rt);
} void update(int l, int r, int rt) {
if(L <= l && r <= R) {
add[rt] += _add;
minx[rt] += _add; //这里直接修改即可
return;
}
pushdown(rt);
int m = MID;
if(L <= m) update(lson);
if(m < R) update(rson);
pushup(rt);
} int main() {
scanf("%d%d", &n, &m);
build(1, n, 1);
int i;
for(i = 1; i <= m; ++i) {
scanf("%d%d%d", &_add, &L, &R);
_add = -_add;
update(1, n, 1);
if(minx[1] < 0) { printf("-1\n%d", i); return 0;}
}
printf("0");
return 0;
}
【wikioi】1217 借教室的更多相关文章
- Codevs 1217 借教室 2012年NOIP全国联赛提高组
1217 借教室 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在大学期间,经常需要租借教 ...
- codevs 1217 借教室
传送门 1217 借教室 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Descripti ...
- 借教室(codevs 1217)
1217 借教室 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Descrip ...
- NOIP 2012 Day2T2 借教室题解
NOIP 2012 Day2T2 借教室题解 题目传送门:http://codevs.cn/problem/1217/ 题目描述 Description 在大学期间,经常需要租借教室.大到院系举办活动 ...
- NOIP2012借教室[线段树|离线 差分 二分答案]
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...
- [NOIP2012] 提高组 洛谷P1083 借教室
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然 ...
- NOIp 2012 #2 借教室 Label:区间修改线段树
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然 ...
- 【NOIP2012】借教室
因为本校OJ+1s所以用线段树水过了,不去syz的水库水这题还真不知道线段树过不了= = 原题: 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的 ...
- NOIP 2012 T5 借教室 [洛谷P1083]
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...
随机推荐
- 完整java开发中JDBC连接数据库代码和步骤 JDBC连接数据库
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.l ...
- STM32canopen调试
问题1:用usbcan监测不到can口的报文 属于接线问题 CANopen程序总使用的是can1 对应的接下口在J1的1和2口,而其接口排序是从外向里排序,故最外面的为1号接口,由于接线时,按照左边的 ...
- scp失效问题
1.症状 (1)登陆到服务器A(已在本机用ssh-add, ssh -A),scp 到服务器B时提示public key有问题: (2)/tmp/下没有ssh-XXX目录 2.原因 服务器A被pupp ...
- Java最常用的变量定义汇总
Java最常用的数据类型有基本数据类型,字符串对象,数组,基本数据类型又分为:数值型(包括整形和浮点型),字符型,布尔型,下面用一个简单的程序把这些数据类型汇总一下 public class Java ...
- Java性能优化权威指南-读书笔记(三)-JVM性能调优-内存占用
新生代.老年代.永久代的概念不多说,这三个空间中任何一个不能满足内存分配请求时,就会发生垃圾收集. 新生代不满足内存分配请求时,发生Minor GC,老年代.永久代不满足内存分配请求时,发生Full ...
- [Android Pro] UI设计师不可不知的安卓屏幕知识
reference to : http://www.android100.org/html/201505/24/149342.html 不少设计师和工程师都被安卓设备纷繁的屏幕搞得晕头转向,我既做UI ...
- MySQL主备库切换(MHA)演练与总结
演练包括被动切换和主动切换两部分.被动切换是主库宕机,主动切换是人工手动触发. 演练步骤大致如下: 1 先停掉主库,模拟主库宕机 2 mha将vip切到备库,备库变成主库, ...
- C++动态内存管理之shared_ptr、unique_ptr
C++中的动态内存管理是通过new和delete两个操作符来完成的.new操作符,为对象分配内存并调用对象所属类的构造函数,返回一个指向该对象的指针.delete调用时,销毁对象,并释放对象所在的内存 ...
- linux之间文件传输问题
如果linux服务器使用了秘钥登陆,可以先关闭秘钥登陆 http://blog.chinaunix.net/uid-23634108-id-2393471.html 然后:scp -P 端口号 no ...
- PHP常用类型判断函数
1.gettype():获取变量类型 2.is_array():判断变量类型是否为数组类型 3.is_double():判断变量类型是否为倍浮点类型 4.is_float():判断变量类型是否为浮点类 ...