题目链接 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;
}