HDU - 1540 Tunnel Warfare(线段树 区间合并)
来源:互联网 发布:德约科维奇出轨知乎 编辑:程序博客网 时间:2024/05/29 16:33
题目大意:给你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[N], rsum[N], tsum[N], mark[N];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;}
0 0
- HDU-1540 Tunnel Warfare 线段树 区间合并
- hdu 1540 Tunnel Warfare(线段树区间合并)
- hdu 1540 & poj 2892 Tunnel Warfare 线段树区间合并
- 【Hdu】1540 Tunnel Warfare(线段树|区间合并)
- HDU 1540 Tunnel Warfare(线段树 区间合并 +单点更新)
- hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】
- HDU 1540 Tunnel Warfare(线段树区间合并)
- HDU 1540 Tunnel Warfare (线段树区间合并)
- HDU - 1540 Tunnel Warfare(线段树 区间合并)
- hdu 1540 Tunnel Warfare (线段树区间合并)
- hdu 1540 Tunnel Warfare 【线段树 区间合并】
- HDU 1540 Tunnel Warfare 线段树区间合并
- HDU 1540 Tunnel Warfare(线段树区间合并)
- HDU 1540 Tunnel Warfare (线段树,区间合并)
- HDU-1540 Tunnel Warfare (线段树区间合并)
- Hdu 1540 Tunnel Warfare【线段树区间合并学习】
- HDU 1540 Tunnel Warfare 线段树区间合并
- HDU 1540Tunnel Warfare Tunnel Warfare (线段树- 区间合并-单点更新查询)
- 34.Rotate Array
- 获取当前目录
- Android中的drawable下的资源使用
- 线性方程组(A是上三角矩阵时)的C++求解
- js-预编译就是那个鬼
- HDU - 1540 Tunnel Warfare(线段树 区间合并)
- QT事件--阐述的比较系统
- [架构师]我要怎么做才能成为一名架构师
- Ubuntu 上文件共享
- 面试中关于字符串的一些问题
- http协议返回值说明
- 交换、路由与防火墙手记(6)
- Android_06_返回Activity时,传递数据
- docker1.9源码分析(三):daemon启动过程