[NOIP2012 TG] 借教室

题目链接
该题目看起来像用线段树,区间修改,单点查询,
其实这题并没有必要用线段树这种高级数据结构,
用小技巧就可以了,差分+前缀和+二分 就可以了。

时间复杂度
差分+前缀和 O(n+m)
二分 O(log2 m)
所以总复杂度O((n+m) log2 m)

#include 
#include 
#include 
#include 
using namespace std;
#define MAXN 1000005

inline void read(int &x){
    char c=getchar();x=0;int flag=0;
    while((!isdigit(c))&&c!='-') c=getchar();
    if(c=='-'){flag=1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    if(flag)x=-x;
}

int n,m;
int r[MAXN],d[MAXN],s[MAXN],t[MAXN];
int delta[MAXN],sum;
int L,R,mid,ans;

int check(int x){
    memset(delta,0,sizeof(delta));
    for(int i=1;i<=x;++i){
        delta[s[i]]+=d[i];
        delta[t[i]+1]-=d[i];
    }
    sum=0;
    for(int i=1;i<=n;++i){
        sum+=delta[i];
        if(sum>r[i]) return 0;
    }   
    return 1;
}

int main(){
    read(n);read(m);
    for(int i=1;i<=n;++i)
        read(r[i]);
    for(int i=1;i<=m;++i){
        read(d[i]);read(s[i]);read(t[i]);
    }
    L=1;R=m;
    while(L<=R){
        mid=(L+R)>>1;
        if(check(mid)==0){
            ans=mid;
            R=mid-1;
        } else{
            L=mid+1;
        }
    }
    if(!ans)
        printf("0\n");
    else{
        puts("-1");
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(竞赛,--小技巧,----差分,----前缀和)