Noip 2012 借教室 - 二分 - 差分

刚看到题的时候秒打了个差分上去,然后发现要输出第一个不满足条件的合同。。。当时以为这是差分的子任务,就觉得这个东西随便找找就好了吧,然后就怎么也找不出来Orz

事实证明,差分确实难打方案。。。

后来才知道找订单才是主要的。。。需要二分答案来着。。。因为题目强制给你单调性了(完成订单的顺序必须满足输入顺序)所以我们可以二分一个最开始不能完成的订单,然后检查这个订单是不是真的不满足就可以了。若这个订单满足,就往后找,反之往左找。

判断就是差分了,每次一个订单需要覆盖区间的时候,把区间的左端点加d[i],右端点+1的位置减d[i],i指的是订单,范围是1到二分的那个答案。最后对某天求前缀和,即可求出某一天需要多少教室

#include 
#include 
#include 
#include 
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 1000000 + 10;
int n,m,seq[MAXN],d[MAXN],r[MAXN],s[MAXN],t[MAXN],ans,temp; 
bool jud(int mid) {
    bool flg = false;
    memset(seq,0,sizeof(seq));
    temp = 0;
    for(int i=1; i<=mid; i++) {
        seq[s[i]]+=d[i];
        seq[t[i]+1]-=d[i]; 
    }
    for(int i=1; i<=n; i++) {
        temp += seq[i];
        if(temp > r[i]) {
            flg = true;
            break;
        }
    }
    return flg;
}
int main() {
    scanf("%d %d",&n,&m);
    for(int i=1; i<=n; i++) 
        scanf("%d", &r[i]);
    for(int i=1; i<=m; i++) 
        scanf("%d %d %d",&d[i],&s[i],&t[i]);
    int l = 1, rr = m;
    while(l <= rr) {
        int mid = l+rr>>1;
        if(jud(mid)) {
            ans = mid;
            rr = mid - 1;   
        }
        else 
            l = mid + 1;
    }
    if(!ans) printf("0");
    else {
        printf("-1\n");
        printf("%d",ans);
    }
    return 0;
}

你可能感兴趣的:(NOIP,差分,二分答案,模拟)