P1083 [NOIP2012 提高组] 借教室

121 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

题目:我们需要处理接下来 n 天的借教室信息,其中第 i 天学校有ri 个教室可供租借。共有 m 份订单,每份订单用三个正整数描述,分别为 dj,sj,tj,表示某租借者需要从第sj 天到第tj 天租借教室(包括第 sj 天和第 tj 天),每天需要租借 dj个教室。

我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供 dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。

现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。 思路:第一种方法是线段树维护区间的最小值和实现区间加法,之后直接做就可以,但是这种做法我吸氧才能过;第二种做法是二分,二分到第几个订单会不满足条件,也就是二分答案,check里面用差分数组来统计判断
代码是线段树的

#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
//#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
const ll mod=998244353;
const ll inf=1e9;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int ro[N];
struct seg{
    int lazy,val;
}t[N<<2];
void pushup(int p){t[p].val=min(t[p<<1].val,t[p<<1|1].val);}
void build(int l,int r,int p){
    t[p].val=t[p].lazy=0;
    if(l==r){
        t[p].val=ro[l];
        return;
    }
    int m=l+r>>1;
    build(l,m,p<<1);
    build(m+1,r,p<<1|1);
    pushup(p);
}
void pushdown(int p){
    t[p<<1].lazy+=t[p].lazy;
    t[p<<1|1].lazy+=t[p].lazy;
    t[p<<1].val+=t[p].lazy;
    t[p<<1|1].val+=t[p].lazy;
    t[p].lazy=0;
}
void update(int L,int R,int l,int r,int p,int c){
    if(l>r||l>R||r<L) return;
    if(l>=L&&r<=R){
        t[p].val+=c;
        t[p].lazy+=c;
        return;
    }
    int m=l+r>>1;
    pushdown(p);
    update(L,R,l,m,p<<1,c);
    update(L,R,m+1,r,p<<1|1,c);
    pushup(p);
}
int query(int L,int R,int l,int r,int p){
    if(l>r||l>R||r<L) return inf;
    if(l>=L&&r<=R) return t[p].val;
    pushdown(p);
    int minn=inf;
    int m=l+r>>1;
    minn=min({query(L,R,l,m,p<<1),query(L,R,m+1,r,p<<1|1),minn});
    pushup(p);
    return minn;
}
struct node{
    int d,s,tj;
    bool operator<(node a){return a.tj<tj;}
}st[N];
int n,m;
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m;
    build(1,n,1);
    for(int i=1;i<=n;i++){
        cin>>ro[i];
        update(i,i,1,n,1,ro[i]);
    }
    for(int i=1;i<=m;i++) cin>>st[i].d>>st[i].s>>st[i].tj;
    for(int i=1;i<=m;i++){
        int minn=query(st[i].s,st[i].tj,1,n,1);
        //cout<<i<<" "<<minn<<endl;
        if(minn<st[i].d){cout<<"-1\n"<<i<<endl;return 0;}
        update(st[i].s,st[i].tj,1,n,1,-st[i].d);
        //cout<<i<<"ssss"<<endl;
    }
    cout<<0<<endl;
    return 0;
}