HDU-1540 Tunnel Warfare 线段树
2012-02-28 10:05
399 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1540
题义是对于一段线段,D x 表示破坏x点,R 表示回复最近一次被破坏的点,Q x表示询问以x点为中心的两头的最长的连续区间。改了2个小时,终于A掉了,吐血啊,尤其是杭电的测试数据,一个点可以破坏多次,这小日本鬼子也忒坏吧,再说了如果一个点破坏多次,八路军叔叔也要修理多次吗,题义与实际既不符合,还是POJ厚道。
该题分两部来做,首先是建立一棵线段树,这颗线段树应该保留有一下信息:
1. 该区间的左连续长度,右连续长度
2. 该区间的覆盖情况(即是否没有发生任何破坏)这是线段树以空间换时间的地方
然后就是求连续的区间长度了,我得出结果的步骤是这样的:
A. 首先判定这个节点(x)是否已经被摧毁,如果摧毁直接返回0
B. 如果没有被摧毁的话,就求1 ~ x-1 的右连续段以及 x+1 ~ N 的左连续段再加上自己本身的1
对于R操作的话,用意个stack就行了,注意杭电的一个点可以被多次破坏。
代码如下:
题义是对于一段线段,D x 表示破坏x点,R 表示回复最近一次被破坏的点,Q x表示询问以x点为中心的两头的最长的连续区间。改了2个小时,终于A掉了,吐血啊,尤其是杭电的测试数据,一个点可以破坏多次,这小日本鬼子也忒坏吧,再说了如果一个点破坏多次,八路军叔叔也要修理多次吗,题义与实际既不符合,还是POJ厚道。
该题分两部来做,首先是建立一棵线段树,这颗线段树应该保留有一下信息:
1. 该区间的左连续长度,右连续长度
2. 该区间的覆盖情况(即是否没有发生任何破坏)这是线段树以空间换时间的地方
然后就是求连续的区间长度了,我得出结果的步骤是这样的:
A. 首先判定这个节点(x)是否已经被摧毁,如果摧毁直接返回0
B. 如果没有被摧毁的话,就求1 ~ x-1 的右连续段以及 x+1 ~ N 的左连续段再加上自己本身的1
对于R操作的话,用意个stack就行了,注意杭电的一个点可以被多次破坏。
代码如下:
#include <cstring> #include <cstdlib> #include <cstdio> #include <stack> #define MAXN 50005 using namespace std; struct Node { int l, r; int lenl, lenr, cover; }seg[MAXN*3]; char rec[MAXN]; void creat(int f, int l, int r) { int mid = (l+r)>>1; seg[f].l = l, seg[f].r = r; seg[f].lenl = r-l; seg[f].lenr = r-l; seg[f].cover = 1; if (r - l > 1) { creat(f<<1, l, mid); creat(f<<1|1, mid, r); } } void modify(int f, int l, int r, int val) { int mid = (seg[f].l + seg[f].r)>>1; if (seg[f].l == l && r == seg[f].r) { seg[f].lenl = seg[f].lenr = val; seg[f].cover = val; } else if (seg[f].r - seg[f].l > 1) { if (seg[f].cover == 1) { // lazy 操作 seg[f<<1].cover = seg[f].cover; seg[f<<1|1].cover = seg[f].cover; seg[f].cover = 0; } if (r <= mid) modify(f<<1, l, r, val); else if (l >= mid) modify(f<<1|1, l, r, val); else { modify(f<<1, l, mid, val); modify(f<<1|1, mid, r, val); } seg[f].lenl = seg[f<<1].lenl; seg[f].lenr = seg[f<<1|1].lenr; if (seg[f<<1].cover == 1) seg[f].lenl += seg[f<<1|1].lenl; if (seg[f<<1|1].cover == 1) seg[f].lenr += seg[f<<1].lenr; // 更新左右区间的连续长度 seg[f].cover = seg[f<<1].cover && seg[f<<1|1].cover; // 回溯cover的值 } } int lquery(int f, int l, int r) { int mid = (seg[f].l+seg[f].r)>>1; if (seg[f].l == l && r == seg[f].r) { return seg[f].lenl; } else if (seg[f].r - seg[f].l > 1) { if (r <= mid) return lquery(f<<1, l, r); else if (l >= mid) return lquery(f<<1|1, l, r); else { int c = lquery(f<<1, l, mid); if (c == mid-l) { c += lquery(f<<1|1, mid, r); } return c; } } else return 0; } int rquery(int f, int l, int r) { int mid = (seg[f].l+seg[f].r)>>1; if (seg[f].l == l && r == seg[f].r) { return seg[f].lenr; } else if (seg[f].r - seg[f].l > 1) { if (r <= mid) return rquery(f<<1, l, r); else if (l >= mid) return rquery(f<<1|1, l, r); else { int c = rquery(f<<1|1, mid, r); if (c == r-mid) { c += rquery(f<<1, l, mid); } return c; } } else return 0; } int main() { int N, M, x; char op[10]; while (scanf("%d %d", &N, &M) == 2) { stack<int>stk; memset(rec, 1, sizeof (rec)); creat(1, 1, N+1); for (int i = 0; i < M; ++i) { scanf("%s", op); if (op[0] == 'R') { if (!stk.empty()) { int c = stk.top(); rec[c] = 1; stk.pop(); modify(1, c, c+1, 1); } } else if (op[0] == 'D') { scanf("%d", &x); rec[x] = 0; stk.push(x); modify(1, x, x+1, 0); } else { scanf("%d", &x); if (rec[x] == 0) printf("0\n"); else printf("%d\n", lquery(1, x+1, N+1)+rquery(1, 1, x)+1); } } } return 0; }
相关文章推荐
- hdu1540 poj2892 Tunnel Warfare 线段树端点更新 SBT
- HDU 1540 Tunnel Warfare(线段树区间合并)
- hdu--1540 Tunnel Warfare(线段树+区间合并)
- HDU 1540 Tunnel Warfare(用set解决线段树中单点查询)
- HDU 1540 Tunnel Warfare (线段树或set水过)
- 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 1540 Tunnel Warfare
- HDU 1540 Tunnel Warfare (线段树,区间合并)
- HDU - 1540 Tunnel Warfare(线段树 区间合并)
- hdu 1540 Tunnel Warfare(线段树区间统计)