您的位置:首页 > 其它

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

2015-10-21 10:17 453 查看
题目大意:给你N个点,相邻的点连线。现在有3种操作

D x:破坏和x相连的线

Q x:x和几个点相连

R:修复刚被破坏的点的连接

解题思路:刚破坏的点可以用一个栈来存储。现在的问题是,怎么求一个点和几个点相连

我们维护区间的三个值,从最左端往右的连续没有被破坏的点数量lsum,从最右端开始往左的连续的没有被破坏的点的数量rsum,区间内最长的连续的没有被破坏的点的数量tsum

询问的时候可以这样做,首先先判断一下该点所属的区间的tsum,如果tsum为0,表示这个区间内没有点连通,那么返回的就是0了,如果tsum == (r - l + 1)表示所有的点都被连接起来了,那么返回(r - l + 1)

如果都不是的话,判断一下该点属于左区间还是右区间

假设属于左区间,那就要判断一下,该点是否在左区间的rsum范围内,如果在该范围内,表示该点和mid相连,所以还得查询一下右区间,找寻和mid + 1相连的点的数量。如果不在rsum的范围内,直接递归查找下去

右区间的情况和左区间的情况类似

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
const int N = 50010 << 2;

int lsum
, rsum
, tsum
, mark
;
int n, m;
void build(int u, int l, int r) {
lsum[u] = rsum[u] = tsum[u] = r - l + 1;
mark[u] = -1;
if (l == r) return ;
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
}

void Update(int u, int l, int r) {
lsum[u] = rsum[u] = tsum[u] = mark[u] ? 0 : r - l + 1;
}

void PushDown(int u, int l, int r) {
if (mark[u] == -1) return ;
mark[u << 1] = mark[u << 1 | 1] = mark[u];
mark[u] = -1;
int mid = (l + r) >> 1;
Update(u << 1, l, mid);
Update(u << 1 | 1, mid + 1, r);
}

void PushUp(int u, int l, int r) {
tsum[u] = max(max(tsum[u << 1], tsum[u << 1 | 1]), rsum[u << 1] + lsum[u << 1 | 1]);
lsum[u] = lsum[u << 1];
rsum[u] = rsum[u << 1 | 1];
int mid = (l + r) >> 1;
if (lsum[u] == mid - l + 1)
lsum[u] += lsum[u << 1 | 1];
if (rsum[u] == r - mid)
rsum[u] += rsum[u << 1];
}

void Modify(int u, int l, int r, int pos, int c) {
if (l == r) {
mark[u] = c;
Update(u, l, r);
return ;
}
PushDown(u, l, r);
int mid = (l + r) >> 1;
if (pos <= mid) Modify(u << 1, l, mid, pos, c);
else Modify(u << 1 | 1, mid + 1, r, pos, c);
PushUp(u, l, r);
}

int Query(int u, int l, int r, int pos) {
if (l == r || tsum[u] == 0 || tsum[u] == r - l + 1)
return tsum[u];
PushDown(u, l, r);
int mid = (l + r) >> 1;
if (pos <= mid) {
int tmp = mid - rsum[u << 1] + 1;
if (pos >= tmp) return Query(u << 1, l, mid, pos) + Query(u << 1 | 1, mid + 1, r, mid + 1);
else return Query(u << 1, l, mid, pos);
}
else {
int tmp = mid + lsum[u << 1 | 1];
if (pos <= tmp) return Query(u << 1 | 1, mid + 1, r, pos) + Query(u << 1, l, mid, mid);
else return Query(u << 1 | 1, mid + 1, r, pos);
}
}

void solve() {
stack<int> Stack;
build(1, 1, n);
char op[4];
int pos;
while (m--) {
scanf("%s", op);
if (op[0] == 'R') {
if (Stack.empty()) continue;
pos = Stack.top();
Stack.pop();
Modify(1, 1, n, pos, 0);
}
else if (op[0] == 'D') {
scanf("%d", &pos);
Stack.push(pos);
Modify(1, 1, n, pos, 1);
}
else {
scanf("%d", &pos);
printf("%d\n", Query(1, 1, n, pos));
}
}
}

int main() {
while (scanf("%d%d", &n, &m) != EOF)  solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: