题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1540
题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少。
其实这题直接二分查找也可以,但用线段树可以练一练手。
大致思路就是找查询点最近的左右两个0的位置(0表示被摧毁的),然后输出区间大小即可,如果这个点已经被摧毁那么就没有
连续的区间,那么输出0。线段树查询位置有点麻烦具体看代码。
#include <iostream> #include <cstring> #include <cstdio> #include <stack> using namespace std; const int M = 5e4 + 10; struct TnT { int l , r , num; }T[M << 2]; int n , m; void build(int l , int r , int p) { int mid = (l + r) >> 1; T[p].l = l , T[p].r = r; if(T[p].l == T[p].r) { T[p].num = 1; return; } build(l , mid , p << 1); build(mid + 1 , r , (p << 1) | 1); T[p].num = T[p << 1].num + T[(p << 1) | 1].num; } void updata(int pos , int p , int ad) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == T[p].r && T[p].l == pos) { T[p].num = ad; return ; } if(mid >= pos) { updata(pos , p << 1 , ad); } else { updata(pos , (p << 1) | 1 , ad); } T[p].num = T[p << 1].num + T[(p << 1) | 1].num; } int queryr(int p , int l , int r) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l >= l && T[p].r <= r) { if(T[p].l == T[p].r) { if(T[p].num == 0) { return T[p].l; } else { return n + 1; } } if(T[p << 1].r - T[p << 1].l + 1 > T[p << 1].num) { return queryr(p << 1 , l , r); } else { return queryr((p << 1) | 1 , l , r); } } if(mid >= r) { return queryr(p << 1 , l , r); } else if(mid < l) { return queryr((p << 1) | 1 , l , r); } else { return min(queryr(p << 1 , l , mid) , queryr((p << 1) | 1 , mid + 1 , r)); } } int queryl(int p , int l , int r) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l >= l && T[p].r <= r) { if(T[p].l == T[p].r) { if(T[p].num == 0) { return T[p].l; } else { return 0; } } if(T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1 > T[(p << 1) | 1].num) { return queryl((p << 1) | 1 , l , r); } else { return queryl(p << 1 , l , r); } } if(mid >= r) { return queryl(p << 1 , l , r); } else if(mid < l) { return queryl((p << 1) | 1 , l , r); } else { return max(queryl(p << 1 , l , mid) , queryl((p << 1) | 1 , mid + 1 , r)); } } int query(int p , int pos) { int mid = (T[p].l + T[p].r) >> 1; if(T[p].l == T[p].r) { return T[p].num; } if(mid >= pos) { return query(p << 1 , pos); } else { return query((p << 1) | 1 , pos); } } int main() { while(~scanf("%d%d" , &n , &m)) { build(1 , n , 1); char cp[2]; stack<int>ss; int mm; for(int i = 0 ; i < m ; i++) { scanf("%s" , cp); if(cp[0] == 'D') { scanf("%d" , &mm); updata(mm , 1 , 0); ss.push(mm); } if(cp[0] == 'Q') { scanf("%d" , &mm); int g = query(1 , mm); if(g == 0) { printf("0 "); continue; } int L = queryl(1 , 1 , mm); int R = queryr(1 , mm , n); printf("%d " , R - L - 1); } if(cp[0] == 'R') { if(!ss.empty()) { int gl = ss.top(); ss.pop(); updata(gl , 1 , 1); } } } } return 0; }