Charging

非常棒的一个二分题(日后可能就是个硬核板子题了)

对于每一个min(tot, x), 我们不妨直接枚举二分x。如果这个x满足满足tot >= x, 即方案数大于等于x的区间交集的数量,那么我们就继续二分。
check函数的写法有点像板子。对于一个区间我们求大于等于x的最大交集区间个数:枚举左端点,对于该左端点的右端点来说,如果区间长度 >= x, 那么我们就继续记录tot, 记录下当前的右端点,然后枚举完当前的左端点的右端点后,动态判断tot(交集区间个数),然后删除对于下一个左端点来说,没有贡献的交集的区间个数(也就时记录下的tot中的有效右端点的个数);
最坏复杂度(o(logm * (n + m))

#include <bits/stdc++.h>

using namespace std;

const int N = 6e5 + 10;

vector<int> L[N];
int n, m;
int R[N];

bool check(int x) {
    memset(R, 0, sizeof R);
    int tot = 0;
    //枚举左端点
    for(int i = 1; i <= n; i ++ ) {
        //枚举右端点
        for(int j : L[i]) {
            if(j - i + 1 >= x) {
                tot ++;
                R[j] ++;
            }
        }
        if(tot >= x) return true;
        //减去当前左端点为i时,右端点不符合的情况数
        tot -= R[i + x - 1];
    }
    return false;
}

int main()
{

    scanf("%d%d", &n, &m);

    for(int i = 1; i <= n; i ++ ) {
        int l, r;
        scanf("%d%d", &l, &r);
        L[l].push_back(r);
    }

    //枚举答案长度(长度合法的话需要tot >= x)
    int l = 1, r = m;
    while(l < r) {
        int mid = l + r + 1 >> 1;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }

    printf("%d\n", l);
    return 0;
}
#二分查找##C/C++#
全部评论
牛客的算法板块有不少二分的算法题,我之前还做过
点赞 回复 分享
发布于 2022-04-21 17:52

相关推荐

点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务