HDU 1540 Tunnel Warfare(线段树)

HDU 1540 Tunnel Warfare

题目链接

题意:n个村庄连成一排,有3种操作

D x 破坏x村庄
R 恢复上一个被破坏的村庄
Q x 询问x村庄所在连续村庄长度

思路:线段树的区间合并,记录区间左边,右边连续,和区间最大连续,由于都是单点操作所以没必要延时了,然后对于恢复操作可以用一个栈记录下之前的操作即可

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)

const int N = 50005;
int n, m;

struct Node {
	int l, r, lsum, rsum, sum;
	int size() {return r - l + 1;}
} node[N * 4];

int st[N], top;

void pushup(int x) {
	node[x].lsum = node[lson(x)].lsum;
	node[x].rsum = node[rson(x)].rsum;
	node[x].sum = max(node[lson(x)].sum, node[rson(x)].sum);
	if (node[lson(x)].lsum == node[lson(x)].size())
		node[x].lsum += node[rson(x)].lsum;
	if (node[rson(x)].rsum == node[rson(x)].size())
		node[x].rsum += node[lson(x)].rsum;
	node[x].sum = max(node[x].sum, node[lson(x)].rsum + node[rson(x)].lsum);
}

void build(int l, int r, int x = 0) {
	node[x].l = l; node[x].r = r;
	if (l == r) {
		node[x].lsum = node[x].rsum = node[x].sum = 1;
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, lson(x));
	build(mid + 1, r, rson(x));
	pushup(x);
}

void add(int v, int val, int x = 0) {
	if (node[x].l == node[x].r) {
		node[x].lsum = node[x].rsum = node[x].sum = val;
		return;
	}
	int mid = (node[x].l + node[x].r) / 2;
	if (v <= mid) add(v, val, lson(x));
	if (v > mid) add(v, val, rson(x));
	pushup(x);
}

int query(int v, int x = 0) {
	if (node[x].l == node[x].r) return node[x].sum;
	if (v < node[lson(x)].r - node[lson(x)].rsum + 1) return query(v, lson(x));
	if (v > node[rson(x)].l + node[rson(x)].lsum - 1) return query(v, rson(x));
	return node[lson(x)].rsum + node[rson(x)].lsum;
}

int main() {
	while (~scanf("%d%d", &n, &m)) {
		build(1, n);
		char op[2]; int v; top = 0;
		while (m--) {
			scanf("%s", op);
			if (op[0] == 'R') add(st[top--], 1);
			else {
				scanf("%d", &v);
				if (op[0] == 'D') {
					add(v, 0);
					st[++top] = v;
				} else printf("%d\n", query(v));
			}
		}
	}
	return 0;
}


你可能感兴趣的:(HDU 1540 Tunnel Warfare(线段树))