• Noip 2012 借教室 (二分答案+差分数组)


    题面

    题目链接

    思路

    朴素的想法我们回去暴力修改区间元素,从而判断教室能否够用,但是看数据范围显然这会超时,既然区间问题我们立马想到前缀和和差分数组,and线段树和树状数组,这里不写树状数组和线段树的做法。我们看数据测试量,然后看了一下,这个答案具有线性性质,所以我们可以二分加速,所以我们二分mid,去找不满足条件的最右点,然后在check里面,我们维护一个差分数组,来保存我们要存的教室的数量,最后累加一次前缀和,发现有元素大于原有教室个数,那么我们就判定这个条件下是行不通的。

    代码实现

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <list>
    #include <map>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <numeric>
    #include<vector>
    #include <functional>
    #define x first
    #define y second 
    using namespace std;
    typedef long long ll;
    const int maxn=1000005;
    int r[maxn],s[maxn],e[maxn],d[maxn],l,ri,cf[maxn],need[maxn];
    int n,m;
    bool check (int mid) {
        memset (cf,0,sizeof (cf));
        for (int i=1;i<=mid;i++) {
          cf[s[i]]+=d[i];
          cf[e[i]+1]-=d[i];
        }
        for (int i=1;i<=n;i++) {
            need[i]=need[i-1]+cf[i];
            if (need[i]>r[i]) return 0; 
        }
        return 1;
    }
    int main () {
        cin>>n>>m;
        for (int i=1;i<=n;i++) cin>>r[i];
        for (int i=1;i<=m;i++) {
           cin>>d[i]>>s[i]>>e[i];
        }
        l=1,ri=m;
        if (check(m)) {
         cout<<0<<endl;
         return 0;
        }
        while (l<ri) {
           int mid=(l+ri)/2;
           if (check(mid)) {
               l=mid+1;
           }
           else ri=mid;
        }
        cout<<-1<<endl<<l;
        return 0;
    }
    
    
  • 相关阅读:
    2020/3/12
    练习题1
    2020/3/26
    2020/3/25
    2020/3/24
    2020/3/23
    应用层
    bzoj3326[SCOI2013]数数
    HEOI2017游记
    bzoj4417[SHOI2013]超级跳马
  • 原文地址:https://www.cnblogs.com/hhlya/p/13193922.html
Copyright © 2020-2023  润新知