【Hdu】1540 Tunnel Warfare(线段树|区间合并)
2015-03-06 16:43
232 查看
题目大意:有N个村子排成一条直线,每个村子都连接了它的左右两个村子(除了最左边和最右边的外),有3种操作,(1)"D x",表示将第x个村子摧毁。(2)"Qx",表示查询与第x个村子直接和间接相连的村子有多少个。(3)"R",表示将上一次摧毁的村子复原。
这边有一个需要注意的点是村子可以多次被摧毁,但只需要一次便可恢复。
思路:
这边我只用两个数组lsum,和rsum
其中作用分别是表示左边界向右连续的最大长度,右边界向左连续的最大长度
然后先询问的函数query中,所采用的是不断缩放区间,直到最后成为一个点,并且缩放后区间的lsum和rsum的意义也发生改变
lsum表示的是左边界向左连续的最大长度,rum表示右边界向右连续的最大长度,这样最后对于询问的点q,lsum表示的就是不包括该点向左连续的最大长度,rsum表示的就是不包括该点向右连续的最大长度。
有了这个思想基础之后,剩下的便是转化了,搞了好久。详细看代码吧。
这边有一个需要注意的点是村子可以多次被摧毁,但只需要一次便可恢复。
思路:
这边我只用两个数组lsum,和rsum
其中作用分别是表示左边界向右连续的最大长度,右边界向左连续的最大长度
然后先询问的函数query中,所采用的是不断缩放区间,直到最后成为一个点,并且缩放后区间的lsum和rsum的意义也发生改变
lsum表示的是左边界向左连续的最大长度,rum表示右边界向右连续的最大长度,这样最后对于询问的点q,lsum表示的就是不包括该点向左连续的最大长度,rsum表示的就是不包括该点向右连续的最大长度。
有了这个思想基础之后,剩下的便是转化了,搞了好久。详细看代码吧。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<algorithm> #include<stack> using namespace std; #define MAX 50005 #define ls rt<<1 #define rs ls|1 #define m (l+r)>>1 int lsum[MAX << 2]; int rsum[MAX << 2]; int bb[MAX]; int ans; void uprt(int len, int rt) { lsum[rt] = lsum[ls]; rsum[rt] = rsum[rs]; if (lsum[rt] == len - (len >> 1)) lsum[rt] += lsum[rs]; if (rsum[rt] == (len >> 1)) rsum[rt] += rsum[ls]; } void updata(int q, int c, int l, int r, int rt) { if (l == r) { lsum[rt] = rsum[rt] = c; bb[l] = c; return; } int mid = m; if (q <= mid) updata(q, c, l, mid, ls); else updata(q, c, mid + 1, r, rs); uprt(r - l + 1, rt); } void query(int q, int l, int r, int rt) { if (l == r) { ans = (lsum[rt] + rsum[rt])*bb[l] + bb[l]; return; } int mid = m; int len = r - l + 1; int a, b; if (q <= mid) { a = rsum[ls]; b = lsum[ls]; if (rsum[ls] != 0) rsum[ls] = lsum[rs]; if (lsum[rs] == (len >> 1)) rsum[ls] += rsum[rt]; lsum[ls] = lsum[rt]; query(q, l, mid, ls); rsum[ls] = a; lsum[ls] = b; } else { a = rsum[rs]; b = lsum[rs]; if (lsum[rs] != 0) lsum[rs] = rsum[ls]; if (rsum[ls] == len - (len >> 1)) lsum[rs] += lsum[rt]; rsum[rs] = rsum[rt]; query(q, mid + 1, r, rs); rsum[rs] = a; lsum[rs] = b; } } void reset(int l, int r, int rt) { if (l == r) return; int mid = m; reset(l, mid, ls); reset(mid + 1, r, rs); uprt(r - l + 1, rt); } void build(int l, int r, int rt) { if (l == r) { rsum[rt] = lsum[rt] = 1; bb[l] = 1; return; } int mid = m; build(l, mid, ls); build(mid + 1, r, rs); uprt(r - l + 1, rt); } int main() { int n, k; char str[2]; int a; while (~scanf("%d%d", &n, &k)) { stack<int>pre; build(1, n, 1); for (int i = 0; i < k; i++) { scanf("%s", str); if (str[0] == 'D') { scanf("%d", &a); pre.push(a); updata(a, 0, 1, n, 1); continue; } if (str[0] == 'Q') { scanf("%d", &a); lsum[1] = 0; rsum[1] = 0; query(a, 1, n, 1); printf("%d\n", ans); continue; } if (!pre.empty()) { while (pre.empty() && bb[pre.top()]) pre.pop(); updata(pre.top(), 1, 1, n, 1); pre.pop(); } } } }
相关文章推荐
- 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 线段树 单点更新,查询区间长度,区间合并
- hdu1540 Tunnel Warfare 线段树区间合并
- HDU1540-Tunnel Warfare-线段树区间合并
- HDU-1540 Tunnel Warfare 线段树 区间合并
- poj 2892 hdu 1540Tunnel Warfare(poj 线段树 区间合并)
- hdu 1540 & poj 2892Tunnel Warfare(线段树区间合并)
- hdu 1540 Tunnel Warfare 线段树--区间合并
- HDU 1540 Tunnel Warfare(线段树单点更新+区间合并)
- hdu 1540 Tunnel Warfare 线段树 区间合并