题目描述:
在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份订单,每份订单用三个正整数描述,分别为dj, sj, tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。
现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
输入描述:
第一行包含两个正整数n, m,表示天数和订单的数量。
第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。
接下来有m行,每行包含三个正整数dj, sj, tj,表示租借的数量,租借开始、结束分别在第几天。
每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。
输出描述:
如果所有订单均可满足,则输出只有一行,包含一个整数0。否则(订单无法完全满足)输出两行,第一行输出一个负整数-1,第二行输出需要修改订单的申请人编号。
题解:
这个题目输入量比较大,所以尽量用快读,不用快读的话c++14也是可以ac的
一共有n天,第i天可租界的教室会告诉你,一共有m组数据,每组数据包含租界起止时间,和租借量,对于某一段时间,我们找出这一段时间的哪天租借数量最少即可,
如果最少的天数大于租界的数量,那么表示这段区间可以租界,不要忘记这一段的值要减去这个租借的值。
如果最少的天数小于租界的数量,那么这段时间吗某些天的数量是不够的,所以不可以租界,直接打断输出即可
用线段是解决这个区间更新最大最小值问题
/*Keep on going Never give up*/ #pragma GCC optimize(3,"Ofast","inline") #include <bits/stdc++.h> const int maxn=4e6+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int mod = 1e9 + 7; using namespace std; using namespace std; int tree[maxn],a[maxn],add[maxn]; template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } void build(int node,int start,int ends){ if(start==ends){ tree[node]=a[start]; return; } int mid=(start+ends)/2; build(2*node,start,mid); build(2*node+1,mid+1,ends); tree[node]=min(tree[2*node],tree[2*node+1]); } void Add(int node,int val){ add[node]+=val; tree[node]+=val; return; } void push_down(int node){ if(!add[node]) return; Add(node*2,add[node]); Add(node*2+1,add[node]); add[node]=0; } void update(int node,int start,int ends,int l,int r,int val){ if(start>=l&&ends<=r) return Add(node,val); int mid=(start+ends)/2; push_down(node); if(l<=mid) update(2*node,start,mid,l,r,val); if(r>mid) update(2*node+1,mid+1,ends,l,r,val); tree[node]=min(tree[node*2],tree[node*2+1]); } int treemin(int node,int start,int ends,int l,int r){ if(start>=l&&ends<=r) return tree[node]; int ans=1e9+10; push_down(node); int mid=(start+ends)/2; if(l<=mid) ans=min(ans,treemin(2*node,start,mid,l,r)); if(r>mid) ans=min(ans,treemin(2*node+1,mid+1,ends,l,r)); return ans; }; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++){ a[i]=read<int>(); } build(1,1,n); //for(int i=1;i<=10;i++) cout<<tree[i]<<endl; for(int i=0;i<m;i++){ int l,r,val; val=read<int>(),l=read<int>(),r=read<int>(); if(treemin(1,1,n,l,r)<val){ //cout<<treemin(1,1,n,l,r)<<endl; printf("-1\n%d\n",i+1); return 0; } else{ update(1,1,n,l,r,-val); } } cout<<0<<endl; return 0; }