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

原文地址:https://www.cnblogs.com/whx666/p/12041538.html

时间: 2024-11-07 03:49:53

POJ2892 Tunnel Warfare 题解的相关文章

hdu1540 &amp;&amp; POJ2892 Tunnel Warfare

[比赛提醒]BestCoder 你报名了吗?(点击报名) [科普]什么是BestCoder?如何参加? Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4513    Accepted Submission(s): 1725 Problem Description During the War of Res

POJ2892 Tunnel Warfare

题解: 树状数组+二分裸题. 对于二分时的细节问题,要仔细分析再确定. 代码: #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<map> #include<set> using namespace std; #define pb push_back #define mp make_pair #define se sec

hdu1540 Tunnel Warfare 线段树/树状数组

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly con

HDU 1540 Tunnel Warfare(线段树,单点更新,区间查询)

Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every vill

HDU 1540 Tunnel Warfare 平衡树 / 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1540 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Gene

HDU 1540 Tunnel Warfare 线段树:单点更新,区间合并

Tunnel Warfare                                  Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Problem Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast

Tunnel Warfare HDU 1540 区间合并+最大最小值

Tunnel Warfare HDU 1540 区间合并+最大最小值 题意 D x是破坏这个点,Q x是表示查询以x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 题解思路 参考的大佬博客 这里巧妙使用了最大值最小值来进行区间的查找.上一行是大佬的详细题解,真的很妙啊. 代码实现 #include<cstdio> #include<cstring> #include<algorithm> #include<stack> #define ls (rt&l

hdu--1540 Tunnel Warfare(线段树+区间合并)

Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was