#二分,差分数组#SSL 2366 洛谷 1083 借教室

题目

问第几个区间加一会使区间内值超过限定值


分析

那么这道题需要用二分答案,然后同时用差分数组判断即可,时间复杂度 O ( n l o g m ) O(nlogm) O(nlogm)


代码

#include <cstdio>
#define rr register
using namespace std;
struct rec{int d,l,r;}a[1000001];
int n,m,rest[1000001],t[1000001];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
inline signed check(int x){
    for (rr int i=1;i<=n;++i) t[i]=0;
    for (rr int i=1;i<=x;++i) t[a[i].l]+=a[i].d,t[a[i].r+1]-=a[i].d;//是不是长得很像树状数组
    for (rr int i=1;i<=n;++i){
        t[i]+=t[i-1];
        if (t[i]>rest[i]) return 0;//超过那么答案肯定不是这个值
    }
    return 1;
}
signed main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=n;++i) rest[i]=iut();
    for (rr int i=1;i<=m;++i) a[i]=(rec){iut(),iut(),iut()};
    if (check(m)) return !putchar(48);
    rr int l=1,r=m-1; 
    while (l<r){
        rr int mid=l+r>>1;
        if (check(mid)) l=mid+1;//答案必然更大
        else r=mid;//缩小查找区间
    }
    return !printf("-1\n%d",l); 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值