zoukankan      html  css  js  c++  java
  • HDU 1540 Tunnel Warfare(线段树区间合并)

    题目链接

    题目大意

      三种操作,破坏一个点,修复最后被破坏的点,询问包含这个点的连续区间的最大长度。

    解题思路

      用线段树维护父节点的前缀最长区间和后缀最长区间。
      父节点的前缀最长区间最小等于左二子的最长前缀区间,如果左儿子的最长前缀区间是整个区间,那么父节点的最长前缀区间则还可以加上右二子的最长前缀区间。父节点的后缀最长区间同理。
      对于询问,询问的位置可能有两种情况,一时pos<=区间中点mid,一是pos>mid。
      对于前者,如果从mid到pos是连续的,则包含mid的区间长度就是答案,也就是tree[rt<<1].post+tree[rt<<1|1].pre,否则继续缩小区间。
      对于后者,如果从mid+1到pos时连续的,那么答案也和上面一样。

    代码

    const int maxn = 1e5+10;
    struct Tree {
        int l, r, len, pre, post;
    } tree[maxn<<2];
    int n, m;
    inline void push_down(int rt) {
        tree[rt].pre = tree[rt<<1].pre;
        tree[rt].post = tree[rt<<1|1].post;
        if (tree[rt<<1].pre==tree[rt<<1].len) tree[rt].pre = tree[rt<<1].pre+tree[rt<<1|1].pre;
        if (tree[rt<<1|1].post==tree[rt<<1|1].len) tree[rt].post = tree[rt<<1|1].post+tree[rt<<1].post;
    }
    void build(int rt, int l, int r) {
        tree[rt].l = l, tree[rt].r = r, tree[rt].len = r-l+1;
        if (l==r) {
            tree[rt].pre = tree[rt].post = 1;
            return;
        }
        int mid = (l+r)>>1;
        build(rt<<1, l, mid);
        build(rt<<1|1, mid+1, r);
        push_down(rt);
    }
    void update(int rt, int pos, int val) {
        if (tree[rt].l==tree[rt].r) {
            tree[rt].post = tree[rt].pre = val;
            return;
        }
        int mid = (tree[rt].l+tree[rt].r)>>1;
        if (mid>=pos) update(rt<<1, pos, val);
        else update(rt<<1|1, pos, val);
        push_down(rt);
    }
    int quary(int rt, int pos) {
        if (tree[rt].l==tree[rt].r) return tree[rt].pre; 
        //如果区间长度大于1,那么只有答案是0的时候会l=r,否则,可能是0,也可能是1
        //总之区间能缩小到l=r,那么这点被破坏就是0,否则就是1
        int mid = (tree[rt].l+tree[rt].r)>>1;
        if (mid>=pos) {
            if (tree[rt<<1].post+pos>mid) return tree[rt<<1].post+tree[rt<<1|1].pre; 
            //区间中点所在的区间左边能否包含pos
            else return quary(rt<<1, pos);
        }
        else {
            if (tree[rt<<1|1].pre+mid>=pos) return tree[rt<<1].post+tree[rt<<1|1].pre;
            //区间中点+1所在的区间右边能否包含pos
            else return quary(rt<<1|1, pos);
        }
    }
    int main() {
        while(cin >> n >> m) {
            stack<int> sk;
            build(1, 1, n);
            for (int i = 1; i<=m; ++i) {
                char ch[5]; scanf("%s", ch);
                if (ch[0]=='D') {
                    int num; scanf("%d", &num);
                    update(1, num, 0); sk.push(num);
                }
                else if (ch[0]=='Q') {
                    int num; scanf("%d", &num);
                    printf("%d
    ", quary(1, num)); 
                }
                else if (!sk.empty()) update(1, sk.top(), 1), sk.pop();
            }
        }
        return 0;
    }
    
  • 相关阅读:
    jmeter导出提取的值或参数化的值到excel
    超级有用的正则表达式
    性能测试监控
    asp.net 多线程
    VS代码格式化快捷键
    JS判断IE版本
    Jquery原创排序table
    将aspx转化为html代码
    Java基本语法——变量
    Entity Framework 中的LazyLoading
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13832629.html
Copyright © 2011-2022 走看看