借教室

题目的意思是只需要找一个人就可以了,还以为要找所有的人,怎么看也看不懂。

这道题懂的不是很彻底,挖

我们利用一个差分数组(差分数组:我们能在O(1)的时间内修改一段区间的值)

举个例子:来自hzwer

比如一开始数列a是0 0 0 0 0 0

前缀和0 0 0 0 0 0

3到5天需要2的教室

将a[3]+=2,a[6]-=2

数列变为0 0 2 0 0 -2

前缀和变为0 0 2 2 2 0

这样我们就很方便的修改了一段区间的值,当我们要查询一个点上的值,只需要求出其前缀和就行了

然后二分前mid  个人,这里满足单调性,只有一个是不满足的,并且我们可以知道是在我们的左边还是不在,那么这就和lower_bound查找差不多了,这个数比我小,那么我就在右边,这个数比我大,那么我就在左边

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1000010
using namespace std;
int n,m;
int d[N],a[N],s[N],t[N],r[N];
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f*=-1;c=getchar();}
    while(c>='0'&&c<='9'){x*=10;x+=c-'0';c=getchar();}
    return x*f;
}
bool C(int x)
{
    int tot=0;
    memset(a,0,sizeof(a));    
    for(int i=1;i<=x;i++) 
    {
        a[s[i]]+=d[i]; a[t[i]+1]-=d[i];
    }
    for(int i=1;i<=n;i++) 
    {
        tot+=a[i]; if(tot>r[i]) return false;
    }
    return true;
}
int main()
{
    n=read(); m=read();
    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,ans=-1;
    while(l<r-1)
    {
        int mid=(l+r)/2;
        if(C(mid)) l=mid; 
        else {ans=mid;r=mid;}
    }
    if(ans==-1) printf("0"); 
    else printf("-1\n%d",ans);
    return 0;
}

 

 

posted @ 2016-11-13 14:03  19992147  阅读(154)  评论(0编辑  收藏  举报