题解 [NOIP2012 提高组] 借教室

发布时间 2023-07-13 23:01:00作者: 2017BeiJiang

*题目链接

首先分析是否具有单调性,题目让求哪个租借人最先不能满足要求,显然,让越多人租借,就越容易满足不了需求,具有单调性。可以使用二分答案。

既然是二分答案,考虑如何 \(check\),观察到对于第 \(i\) 名租借者,需要从第 \(s_i\) 天到第 \(t_i\) 天,每天租借 \(d_i\) 间教室,也就是对教室序列执行区间减操作。

由于操作不需要在线,故可以使用差分实现修改。

代码:

const int N=1e6+10;
int n,m;
int r[N],d[N],s[N],t[N];
LL diff[N],sum[N];

int check(int x) {//第x个人
    memset(diff,0,sizeof(diff));
    memset(sum,0,sizeof(sum));

    for(int i=1;i<=n;i++) {
        diff[i]=r[i]-r[i-1];
    }
    for(int i=1;i<=x;i++) {
        diff[s[i]]-=d[i];
        diff[t[i]+1]+=d[i];
    }
    for(int i=1;i<=n;i++) {
        sum[i]=sum[i-1]+diff[i];
        if(sum[i]<0) return 1;
    }
    return 0;
}

int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++) {
        r[i]=read();
    }
    for(int i=1;i<=m;i++) {
        d[i]=read(); s[i]=read(); t[i]=read();
    }
    int l=1,r=m;

    while(l<r) {
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    if(!check(r)) cout<<0;
    else cout<<"-1\n"<<r;


    return 0;
}