• POJ2892 Tunnel Warfare 题解


    POJ2892 Tunnel Warfare

    线段树例题解析合集

    题意:有一条相邻节点相连的链(1和2,2和3,...n-1和n相连),有3种操作:1、破坏某一个节点 2、问从某个点可以到的点有多少个,即中间没有被破坏的点(包括自己) 3、重建当前最后一个被破坏的点

    建立线段树维护每个点能到达的左右边界(初始值都为1,n),破坏一个点k时(设k能到达的左右边界为l1,r1),将l1到k-1的区间内的点的右边界修改为k,将k+1到r1的区间内的点的左边界修改为k

    用一个栈存储点的破坏顺序,重建一个点时,取出栈顶p(设p能到达的左右边界为l2,r2),将l2到k-1的区间内的点的右边界修改为r2,将k+1到r2的区间内的点的左边界修改为l2

    查询时直接用左右边界相减再+1即可

    (蒟蒻的代码可能不具有很强的可读性,但主体部分还是比较清楚的)

    #include <stdio.h>
    #include <iostream>
    using namespace std;
    inline void read (int &x) {
        char ch = getchar(); x = 0;
        while (!isdigit(ch)) ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
    }
    void print (int x) {
        if (x > 9) print (x / 10);
        putchar (x % 10 + 48);
    }
    const int N = 5e4 + 10;
    int n, m, x, top, st[N], ll[N], rr[N], k[N], cl[N << 3], cr[N << 3];
    char ch[5];
    #define ls p << 1
    #define rs p << 1 | 1
    inline void push_down (int p) {
        if (cl[p]) cl[ls] = cl[rs] = cl[p], cl[p] = 0;
        if (cr[p]) cr[ls] = cr[rs] = cr[p], cr[p] = 0;
    }
    void build (int p, int l, int r) {
        if (l == r) {cl[l] = 1, cr[l] = n; return;}
        int mid (l + r >> 1);
        build (ls, l, mid), build (rs, mid + 1, r);
    }
    void update1 (int p, int l, int r, int ql, int qr, int v) {      //修改右边界
        if (ql <= l && qr >= r) {cr[p] = v; return;}
        if (l == r) {rr[l] = cr[p]; return;}
        push_down (p);
        int mid (l + r >> 1);
        if (ql <= mid) update1 (ls, l, mid, ql, qr, v);
        if (qr > mid) update1 (rs, mid + 1, r, ql, qr, v);
    }
    void update2  (int p, int l, int r, int ql, int qr, int v) {     //修改左边界
        if (ql <= l && qr >= r) {cl[p] = v; return;}
        if (l == r) {ll[l] = cl[p]; return;}
        push_down (p);
        int mid (l + r >> 1);
        if (ql <= mid) update2 (ls, l, mid, ql, qr, v);
        if (qr > mid) update2 (rs, mid + 1, r, ql, qr, v);
    }
    void query (int p, int l, int r, int pos) { //使这个点的所有懒标记更新(更新为真实值)
        if (l == r) {ll[l] = cl[p], rr[l] = cr[p]; return;}
        push_down (p);
        int mid (l + r >> 1);
        pos <= mid ? query (ls, l, mid, pos) : query (rs, mid + 1, r, pos);
    }
    int main() {
        read (n), read (m);
        build (1, 1, n);
        for (int i = 1; i <= n; ++i) ll[i] = 1, rr[i] = n;
        while (m--) {
            scanf ("%s", ch);
            if (ch[0] == 'D') {
                read (x);
                st[++top] = x, k[x] = 1, query (1, 1, n, x);
                update1 (1, 1, n, ll[x] - (ll[x] != 1), x - 1, x - 1);
                update2 (1, 1, n, x + 1, rr[x] + (rr[x] != n), x + 1);
            }
            else if (ch[0] == 'Q') {
                read (x);
                if (k[x]) puts ("0");
                else query (1, 1, n, x), print (rr[x] - ll[x] + 1), puts ("");
            }
            else {
                if (!top) continue;
                x = st[top--], k[x] = 0, query (1, 1, n, x);
                update1 (1, 1, n, ll[x] - (ll[x] != 1), x - 1, rr[x]);
                update2 (1, 1, n, x + 1, rr[x] + (rr[x] != n), ll[x]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Spring Session Logout
    VC6.0 error LNK2001: unresolved external symbol _main解决办法
    JDBC数据库编程基本流程
    JDBC连接SQL Server2008
    JDK的下载、安装及环境变量的配置
    奇数阶幻方口诀
    ping: sendto: Network is unreachable
    new/delete和malloc/free的区别
    MFC的消息管理
    VC++之自定义消息
  • 原文地址:https://www.cnblogs.com/whx666/p/12041538.html
Copyright © 2020-2023  润新知