链接:http://poj.org/problem?id=2892
题意:有n个村庄排成一排,三种操作:
1. D x 摧毁村庄x
2. Q x 询问村庄x的最长一段没有被摧毁的村庄数量
3. R 恢复上一个被摧毁的村庄
思路:线段树区间合并,lsum记录当前节点往左的最长连续距离,rsum记录当前节点往右的最长连续距离。
#include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio> #include<cctype> #include<algorithm> #include<queue> #include<map> #include<set> #include<vector> #include<stack> #include<ctime> #include<cstdlib> #include<functional> #include<cmath> using namespace std; #define PI acos(-1.0) #define MAXN 50100 #define eps 1e-7 #define INF 0x3F3F3F3F //0x7FFFFFFF #define LLINF 0x3F3F3F3F3F3F3F3F //0x7FFFFFFFFFFFFFFF #define seed 1313131 #define MOD 1000000007 #define ll long long #define ull unsigned ll #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[MAXN << 2], lsum[MAXN << 2], rsum[MAXN << 2]; int num[MAXN]; int n; void pushup(int rt, int m){ lsum[rt] = lsum[rt << 1]; rsum[rt] = rsum[rt << 1 | 1]; if(lsum[rt] == (m - (m >> 1))) lsum[rt] += lsum[rt << 1 | 1]; if(rsum[rt] == (m >> 1)) rsum[rt] += rsum[rt << 1]; sum[rt] = max(lsum[rt << 1 | 1] + rsum[rt << 1], max(sum[rt << 1], sum[rt << 1 | 1])); } void build(int l, int r, int rt){ sum[rt] = lsum[rt] = rsum[rt] = r - l + 1; if(l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); } void update(int k, int c, int l, int r, int rt){ if(l == r){ sum[rt] = lsum[rt] = rsum[rt] = c; return ; } int m = (l + r) >> 1; if(k <= m) update(k, c, lson); else update(k, c, rson); pushup(rt, r - l + 1); } int query(int pos, int l, int r, int rt){ if(l == r) return sum[rt]; int m = (l + r) >> 1; if(m >= pos){ if(pos >= m - rsum[rt << 1] + 1) return lsum[rt << 1 | 1] + rsum[rt << 1]; else return query(pos, lson); } else{ if(pos <= m + lsum[rt << 1 | 1] + 1) return lsum[rt << 1 | 1] + rsum[rt << 1]; else return query(pos, rson); } } stack<int>s; int main(){ int i, j, m, c; char str[5]; while(scanf("%d%d", &n, &m) != EOF){ build(1, n, 1); while(!s.empty()) s.pop(); memset(num, 0, sizeof(int) * (n + 5)); while(m--){ scanf("%s", str); if(str[0] == 'R'){ if(!s.empty()){ c = s.top(); s.pop(); num[c]--; if(num[c] == 0) update(c, 1, 1, n, 1); } } else{ scanf("%d", &c); if(str[0] == 'D'){ if(num[c] == 0) update(c, 0, 1, n, 1); num[c]++; s.push(c); } else{ if(num[c]){ puts("0"); continue; } printf("%d\n", query(c, 1, n, 1)); } } } } return 0; }
POJ--2892--Tunnel Warfare【线段树】区间合并
原文:http://blog.csdn.net/zzzz40/article/details/41083483