题目描述:
在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来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;

}