zoukankan      html  css  js  c++  java
  • 洛谷 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;
    }
    
    
  • 相关阅读:
    Spring Security简单的登陆验证授权
    汽车之家汽车品牌Logo信息抓取 DotnetSpider实战[三]
    汽车之家店铺商品详情数据抓取 DotnetSpider实战[二]
    如何解决 MySQL报错:ERROR 1045 (28000)
    linux三剑客grep|sed|awk实践
    VMware中Linux启动时***Host SMBus controller not enabled的解决方法
    selenium初探:WebDriverException解决方法探索(以Chrome浏览器|IE浏览器|Edge浏览器为例)
    Windows10 64位 Python2.7 Matplotlib安装
    关于 水平制表符 Horizontal Tab (TAB)
    leetcode每日解题思路 221 Maximal Square
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10891279.html
Copyright © 2011-2022 走看看