【NOIP2012】借教室
来源:互联网 发布:网络销售的经营范围 编辑:程序博客网 时间:2024/05/16 08:49
1217 借教室 2012年NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题解
题目描述 Description
在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份订单,每份订单用三个正整数描述,分别为dj, sj, tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。
现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
输入描述 Input Description
第一行包含两个正整数n, m,表示天数和订单的数量。
提高组 day2
第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。
接下来有m行,每行包含三个正整数dj, sj, tj,表示租借的数量,租借开始、结束分别在第几天。
每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。
输出描述 Output Description
如果所有订单均可满足,则输出只有一行,包含一个整数 0。否则(订单无法完全满足)
输出两行,第一行输出一个负整数-1,第二行输出需要修改订单的申请人编号。
样例输入 Sample Input
4 3
2 5 4 3
2 1 3
3 2 4
4 2 4
样例输出 Sample Output
-1
2
数据范围及提示 Data Size & Hint
第 1 份订单满足后,4 天剩余的教室数分别为 0,3,2,3。第 2 份订单要求第 2 天到第 4 天每天提供 3 个教室,而第 3 天剩余的教室数为 2,因此无法满足。分配停止,通知第2 个申请人修改订单。
【数据范围】
对于 10%的数据,有1 ≤ n, m ≤ 10;
对于 30%的数据,有1 ≤ n, m ≤ 1000;
对于 70%的数据,有1 ≤ n, m ≤ 105;
对于 100%的数据,有1 ≤ n, m ≤ 10^6, 0 ≤ ri, dj≤ 10^9, 1 ≤ sj≤ tj≤ n。
正解二分 因为对于每天 教室数量 都满足二分性质
然而 线段树可以A
仍然推荐二分 线段树空间吓人QAQ
1.二分做法
//命名是拼音
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 1000005;int n,m;int num[MAXN],l[MAXN],r[MAXN];int js[MAXN],zj[MAXN];bool can(int x){ memset(num,0,sizeof(num)); int ans = 0; for(int i = 1; i <= x; i ++) { num[l[i]] -= zj[i]; num[r[i] + 1] += zj[i]; } for(int i = 1; i <= n; i ++) { ans += num[i]; if(ans + js[i] < 0) return false; } return true;}int main(){ memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); memset(js,0,sizeof(js)); memset(zj,0,sizeof(zj)); scanf("%d %d",&n,&m); for(int i = 1; i <= n; i ++) scanf("%d",&js[i]); for(int i = 1; i <= m; i ++) scanf("%d %d %d",&zj[i],&l[i],&r[i]); if(can(m)) { puts("0"); return 0; } int ll = 1,rr = m; while(ll < rr) { int mid = (ll + rr) >> 1; if(can(mid)) ll = mid + 1; else rr = mid; } puts("-1"); printf("%d\n",rr); return 0;}
2.线段树
有一定概率有一个点被卡TLE
总之同样的代码一会AC一会TLE我也很尴尬QAQ
#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <cmath>#define L(x) (x << 1)#define R(x) (x << 1 | 1)#define sz(x) (tree[x].r - tree[x].l + 1)using namespace std;const int MAXN = 9000000 + 5;int num[2000000 + 5];int n,m,l,r,v;struct tree{ int l,r,add; int zx;//最小 }tree[MAXN];int min(int x,int y){ return x < y ? x : y;}void update(int p){ tree[p].zx = min(tree[L(p)].zx,tree[R(p)].zx); return;}void spread(int p){ if(!tree[p].add) return; tree[L(p)].add += tree[p].add; tree[R(p)].add += tree[p].add; tree[L(p)].zx += tree[p].add; tree[R(p)].zx += tree[p].add; tree[p].add = 0; update(p); return;}void build(int l,int r,int p){ tree[p].l = l,tree[p].r = r; if(l == r) { tree[p].zx = num[l]; tree[p].add = 0; return; } int mid = (l + r) >> 1; build(l,mid,L(p)); build(mid + 1,r,R(p)); update(p); return;}int ask_min(int l,int r,int p){ if(l <= tree[p].l && tree[p].r <= r) return tree[p].zx; int ans = 2147483647,mid = (tree[p].l + tree[p].r) >> 1; spread(p); if(l <= mid) ans = min(ans,ask_min(l,r,L(p))); if(mid < r) ans = min(ans,ask_min(l,r,R(p))); update(p); return ans;}void change(int l,int r,int p,int v){ if(l <= tree[p].l && tree[p].r <= r) { tree[p].add += v; tree[p].zx += v; return; } spread(p); int mid = (tree[p].r + tree[p].l) >> 1; if(l <= mid) change(l,r,L(p),v); if(mid < r) change(l,r,R(p),v); update(p); return;}inline void scanf(int &x){ x = 0; char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = (x << 3) + (x << 1);// *=10 x += c - '0'; c = getchar();//??? 1 } return;} int main(){ memset(num,0,sizeof(num)); scanf(n);scanf(m); for(int i = 1; i <= n; i ++) scanf(num[i]); build(1,n,1); for(int i = 1; i <= m; i ++) { scanf(v);scanf(l);scanf(r); if(ask_min(l,r,1) < v) { printf("-1\n%d\n",i); return 0; } change(l,r,1,-v); } puts("0"); return 0;}
- noip2012 借教室
- NOIP2012 借教室
- NOIP2012 借教室
- NOIP2012 借教室
- NOIp2012 借教室
- 1266. [NOIP2012] 借教室
- NOIP2012 借教室(classroom)
- noip2012借教室
- NOIP2012 借教室【二分】
- NOIP2012 借教室
- 【NOIP2012】codevs1217 借教室
- [NOIP2012] 借教室
- 【NOIP2012】借教室
- 【Noip2012】借教室
- [Noip2012]借教室
- [NOIP2012 TG] 借教室
- NOIp2012借教室题解
- NOIP2012借教室
- 二:初学者易犯错误模型
- Android 自定义view实现水波纹效果
- Eclipse+Maven创建webapp项目<一>
- libpcap几个例子
- nd4j 矩阵(matrix)repeat重写 性能150倍提升(干货!)
- 【NOIP2012】借教室
- android小项目
- MacOSX显示桌面by鼠标,无需触控板手势和APP
- NPOI 合并单元格
- web:nginx Beginner’s Guide
- 欢迎使用CSDN-markdown编辑器
- Android逆向之旅---带你爆破一款应用的签名验证问题
- iOS技巧之获取本机通讯录中的内容,解析通讯录源代码
- swift3.0 中... 和 ..<