• 洛谷 P3071 [USACO13JAN]座位Seating(线段树)


    P3071 [USACO13JAN]座位Seating

    题目链接

    思路:

    一开始把题给读错了浪费了好多时间呜呜呜。
    因为第二个撤离操作是区间修改,所以我们可以想到用线段树来做。对于第一个操作,我们只需要维护suml,sumr,sum分别表示当前结点左端连续有多少个空位、右端连续有多少个空位、以及最长连续空位为多少就行了。因为每次安排作为可能会跨过mid,所以我们还需要数组来维护一下信息。
    注意一下代码的细节吧:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 5e5 + 5;
    int n, m;
    int c[N];
    char s[2] ;
    int sum[N << 2], lazy[N << 2], suml[N << 2], sumr[N << 2];
    void build(int o, int l, int r) {
        sum[o] = suml[o] = sumr[o] = r - l + 1;
        if(l == r) return ;
        int mid = (r + l) >> 1;
        build(o << 1, l, mid);
        build(o << 1|1, mid + 1, r) ;
    }
    void pushdown(int o, int l, int r) {
        if(lazy[o] != 0) {
            int mid = (l + r) >> 1 ;
            suml[o << 1] = sumr[o << 1] = sum[o << 1] = (lazy[o] > 0) * (mid - l + 1);
            suml[o << 1|1] = sumr[o << 1|1] = sum[o << 1|1] = (lazy[o] > 0) * (r - mid);
            lazy[o << 1|1] = lazy[o << 1] = lazy[o] ;
            lazy[o] = 0;
        }
    }
    void push_up(int o, int l, int r) {
        int mid = (r + l) >> 1;
        sum[o] = max(max(sum[o << 1], sum[o << 1|1]), sumr[o << 1] + suml[o << 1|1]) ;
        suml[o] = suml[o << 1] + (suml[o << 1] == (mid - l + 1) ? suml[o << 1|1] : 0) ;
        sumr[o] = sumr[o << 1|1] + (sumr[o << 1|1] == (r - mid) ? sumr[o << 1] : 0) ;
    }
    void update(int o, int l, int r, int L, int R, int sign) {
        if(L <= l && r <= R) {
            lazy[o] = sign ;
            suml[o] = sumr[o] = sum[o] = (sign > 0) * (r - l + 1) ;
            return ;
        }
        pushdown(o, l, r) ;
        int mid = (l + r) >> 1;
        if(L <= mid) update(o << 1, l, mid, L, R, sign) ;
        if(R > mid) update(o << 1|1, mid + 1, r, L, R, sign) ;
        push_up(o, l, r) ;
    }
    int ask(int o, int l, int r, int x) {
        int mid = (l + r) >> 1;
        pushdown(o, l, r) ;
        if(sum[o << 1] >= x) return ask(o << 1, l, mid, x) ;
        else if(sumr[o << 1] + suml[o << 1|1] >= x) return mid - sumr[o << 1] + 1;
        else return ask(o << 1|1, mid + 1,r ,x);
    }
    int main() {
        cin >> n >> m;
        int ans = 0;
        build(1, 1, n) ;
        for(int i = 1, a, b; i <= m; i++) {
            scanf("%s", s);
            if(s[0] == 'A') {
                scanf("%d", &a);
                if(sum[1] < a) ans++;
                else {
                    int pos = ask(1, 1, n, a) ;
                    update(1, 1, n, pos, pos + a -1, -1) ;
                }
            } else {
                scanf("%d%d", &a, &b);
                update(1, 1, n, a, b, 1) ;
            }
        }
        cout << ans;
        return 0;
    }
    
    
  • 相关阅读:
    【HDOJ5971】Wrestling Match(二分图,并查集)
    【HDOJ5978】To begin or not to begin(概率)
    【HDOJ5979】Convex(三角函数)
    【HDOJ5980】Find Small A(签到)
    【HDOJ5949】Relative atomic mass(签到)
    【HDOJ5948】Thickest Burger(签到)
    【HDOJ6228】Tree(树)
    【HDOJ6227】Rabbits(贪心)
    147.命题逻辑
    146.离散数学
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10891279.html
Copyright © 2020-2023  润新知