• 【AtCoder ARC076】F Exhausted? 霍尔定理+线段树


    题意

    N个人抢M个椅子,M个椅子排成一排 ,第i个人只能坐[1,Li]∪[Ri,M],问最多能坐多少人


    $i$人连边向可以坐的椅子构成二分图,题意即是求二分图最大完美匹配,由霍尔定理,答案为$max(|X|-omega(X))$,$X$为人的集合,$omega(X)$可以表示为$[1,l] cup[r,M]$,所以可以枚举$omega(X)$也就是$(l,r)$,求出最大的$|X|$,也就是满足$L_ile l land r le R_i$的$i$的数量,也就是平面上以$(l,r)$为原点第二象限的点的数量,可以利用扫描线算法解决

    时间复杂度$O(nlog n)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 200005;
    int n, m, L, R;
    vector<int> val[N];
    int lch[N << 2], rch[N << 2], Max[N << 2], lazy[N << 2];
    inline void update(int x, int v) {
        lazy[x] += v; Max[x] += v;
    }
    inline void pushup(int x) {Max[x] = max(Max[x << 1], Max[x << 1 | 1]);}
    inline void pushdown(int x) {
        if(lazy[x]) {
            update(x << 1, lazy[x]); update(x << 1 | 1, lazy[x]); lazy[x] = 0; 
        }
    }
    void build(int x,int l, int r) {
        lch[x] = l; rch[x] = r;
        if(l == r) {
            Max[x] = l; return;
        }
        int mid = (l + r) / 2;
        build(x << 1, l, mid); build(x << 1 | 1, mid + 1, r);
        pushup(x);
    }
    void update(int x, int l, int r, int v) {
        if(l <= lch[x] && rch[x] <= r) {
            update(x, v); return;
        }
        pushdown(x);
        int mid = (lch[x] + rch[x]) / 2;
        if(r <= mid) update(x << 1, l, r, v);
        else if(l > mid) update(x << 1 | 1, l, r, v);
        else update(x << 1, l, mid, v), update(x << 1 | 1, mid + 1, r, v);
        pushup(x);
    }
    int query(int x, int l, int r) {
        if(l <= lch[x] && rch[x] <= r) {
            return Max[x];
        }
        pushdown(x);
        int mid = (lch[x] + rch[x]) / 2;
        if(r <= mid) return query(x << 1, l, r);
        else if(l > mid) return query(x << 1 | 1, l, r);
        else return max(query(x << 1, l, mid), query(x << 1 | 1, mid + 1, r));
    }
    int ans = 0;
    int main() {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) {
            scanf("%d%d", &L, &R); val[L].push_back(R);
        }
        build(1, 0, m + 1);
        for(int i = 0; i <= m; ++i) {
            for(int j = 0; j < val[i].size(); ++j) {
                update(1, 0, val[i][j], 1);
            }
            ans = max(ans, query(1, i + 1, m + 1) - m - i - 1);
        }
        printf("%d
    ", max(ans, n - m));
        return 0;
    }
    

  • 相关阅读:
    PS选区认识
    移动工具
    PS认识及新建文件
    第02组 Alpha冲刺(3/4)
    第02组 Alpha冲刺(2/4)
    第02组 Alpha冲刺(1/4)
    第02组 团队Git现场编程实战
    第二次结对编程作业
    团队项目-需求分析报告
    团队项目-需求分析报告
  • 原文地址:https://www.cnblogs.com/ogiso-setsuna/p/8455396.html
Copyright © 2020-2023  润新知