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;
}

猜你喜欢

转载自www.cnblogs.com/whx666/p/12041538.html