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