https://ac.nowcoder.com/acm/problem/16564
题意:
已知每天可以借出去的教室数量a[i],根据先到先得原则,按顺序分配教室,共有m个订单,第i个订单需要[li,ri]区间内借xi个教室,问到第几个订单开始无法满足(教室不够了)
分析:
m次区间[li,ri]进行修改xi,边修改边查询是否满足题意,这不就是练习线段树的题目吗?
首先建一颗含最小值信息的线段树,模拟题意进行区间修改,修改完后判断一下整个区间最小值是否小于0,即minx[1]是否小于0,若发现一不符合的修改,直接return 0。
暴力即优雅,记得开longlong(不建议define int long long 费时费空间).
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define int long long//补救措施开longlong
int n,m;
int a[1000005],lazy[4000005],minx[4000005];//懒标记数组和区间最小值数组
void build(int node,int l,int r){//建含最小值的线段树
if(l==r){
minx[node]=a[l];
return ;
}
int mid=(l+r)>>1;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
minx[node]=min(minx[node<<1],minx[node<<1|1]);
}
void pushup(int node){//向下更新
if(lazy[node]){
minx[node<<1]+=lazy[node];
minx[node<<1|1]+=lazy[node];
lazy[node<<1]+=lazy[node];
lazy[node<<1|1]+=lazy[node];
lazy[node]=0;
}
}
void update(int node,int l,int r,int start,int end,int num){//区间修改
if(l>=start&&r<=end){
minx[node]+=num;
lazy[node]+=num;
return ;
}
pushup(node);
int mid=(l+r)>>1;
if(start<=mid)update(node<<1,l,mid,start,end,num);
if(end>mid)update(node<<1|1,mid+1,r,start,end,num);
minx[node]=min(minx[node<<1],minx[node<<1|1]);
}
signed main()
{
memset(minx,0x3f3f3f,sizeof(minx));//初始化最小值
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);//建树
for(int i=1;i<=m;i++){
int d,s,tt;
cin>>d>>s>>tt;
update(1,1,n,s,tt,-d);
//for(int i=1;i<=6;i++) cout<<t[i].minn<<" ";
if(minx[1]<0){
cout<<-1<<endl;
cout<<i<<endl;
return 0;
}
}
cout<<0<<endl;
}
京公网安备 11010502036488号