zoukankan      html  css  js  c++  java
  • 洛谷P1503 鬼子进村 题解 线段树+二分

    题目链接:https://www.luogu.com.cn/problem/P1503

    解题思路:

    用线段树维护区间和,一开始所有的位置对应的值为 (1),如果有一个房间被摧毁,更新为 (0);被修复,更新为 (1)

    查询以 (x) 结尾和开头的最长连续 (1),可以用二分+线段树求区间和。

    实现复杂度 (O(n cdot log n cdot log n))

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 50050;
    int tree[maxn<<2];
    void push_up(int rt) {
        tree[rt] = tree[rt<<1] + tree[rt<<1|1];
    }
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    void update(int p, int x, int l, int r, int rt) {
        if (l == r) tree[rt] = x;
        else {
            int mid = (l + r) / 2;
            if (p <= mid) update(p, x, lson);
            else update(p, x, rson);
            push_up(rt);
        }
    }
    int query(int L, int R, int l, int r, int rt) {
        if (L <= l && r <= R) return tree[rt];
        int mid = (l + r) / 2, ans = 0;
        if (L <= mid) ans += query(L, R, lson);
        if (R > mid) ans += query(L, R, rson);
        return ans;
    }
    void build(int l, int r, int rt) {
        if (l == r) {
            tree[rt] = 1;
            return;
        }
        int mid = (l + r) / 2;
        build(lson);
        build(rson);
        push_up(rt);
    }
    stack<int> stk;
    int n, m, x;
    char ch[2];
    int main() {
        scanf("%d%d", &n, &m);
        build(1, n, 1);
        while (m --) {
            scanf("%s", ch);
            if (ch[0] == 'D') {
                scanf("%d", &x);
                update(x, 0, 1, n, 1);
                stk.push(x);
            }
            else if (ch[0] == 'R') {
                if (!stk.empty()) {
                    x = stk.top();
                    stk.pop();
                    update(x, 1, 1, n, 1);
                }
            }
            else {
                scanf("%d", &x);
                if (query(x, x, 1, n, 1) == 0) {
                    puts("0");
                    continue;
                }
                int L, R, res1 = x, res2 = x;
                L = 1, R = x;
                while (L <= R) {
                    int mid = (L + R) / 2;
                    if (query(mid, x, 1, n, 1) == x-mid+1) {
                        res1 = mid;
                        R = mid-1;
                    }
                    else L = mid+1;
                }
                L = x, R = n;
                while (L <= R) {
                    int mid = (L + R) / 2;
                    if (query(x, mid, 1, n, 1) == mid-x+1) {
                        res2 = mid;
                        L = mid+1;
                    }
                    else R = mid-1;
                }
                printf("%d
    ", res2 - res1 + 1);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    获取成本
    销售订单跟踪成本
    装机
    这就是用战术上的勤奋掩盖战略上的懒惰
    CPA-计划(参考)
    大帝名言
    BZOJ 2100: [Usaco2010 Dec]Apple Delivery spfa
    BZOJ 2834: 回家的路 Dijkstra
    BZOJ 4070: [Apio2015]雅加达的摩天楼 根号分治+spfa
    BZOJ 4152: [AMPPZ2014]The Captain Dijkstra+贪心
  • 原文地址:https://www.cnblogs.com/quanjun/p/13395807.html
Copyright © 2011-2022 走看看