题目链接:hdu 1540
题目大意:D x 表示x位置被炸毁, R表示修复最近被炸毁的点,Q x 表示查询包括x点在内连续最大的区间并且满足这段中都是没有被炸毁。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 50000+10
#define lson left, mid, rt<<1
#define rson mid + 1, right, rt<<1|1
int tree[maxn<<2];
int l_max[maxn<<2], r_max[maxn<<2];
void build(int left, int right, int rt)
{
tree[rt] = l_max[rt] = r_max[rt] = right-left+1;
if(left == right) return;
int mid = (left + right)>>1;
build(left, mid, rt<<1);
build(mid + 1, right, (rt<<1)|1);
}
void pushUp(int rt, int m)
{
l_max[rt] = l_max[rt<<1];
r_max[rt] = r_max[(rt<<1)|1];
if(l_max[rt] == m-(m>>1))
l_max[rt] += l_max[(rt<<1)|1];
if(r_max[rt] == (m>>1))
r_max[rt] += r_max[rt<<1];
tree[rt] = max(tree[rt<<1], tree[(rt<<1)|1]);
tree[rt] = max(tree[rt], r_max[rt<<1] + l_max[(rt<<1)|1] - 1);
}
void upDate(int pos, int change, int left, int right, int rt)
{
if(left == right){
tree[rt] = l_max[rt] = r_max[rt] = change? 1:0;
return ;
}
int mid = (left + right)>>1;
if(pos <= mid)
upDate(pos, change, left, mid, rt<<1);
else if(pos > mid)
upDate(pos, change, mid + 1, right, (rt<<1)|1);
pushUp(rt, right-left+1);
}
int query(int pos, int left, int right, int rt)
{
if(left == right || (tree[rt] == 0) || (tree[rt] == right-left+1)){
return tree[rt];
}
int mid = (left + right)>>1;
if(pos <= mid){
if(pos >= mid- r_max[rt<<1] + 1){
return r_max[rt<<1] + l_max[(rt<<1)|1];
}
else return query(pos, left, mid, rt<<1);
}
else if(pos > mid){
if(pos <= l_max[(rt<<1)|1] + mid){
return r_max[rt<<1] + l_max[(rt<<1)|1];
}
else return query(pos, mid + 1, right, (rt<<1)|1);
}
}
int main()
{
int n, m, p; char op;
while(~scanf("%d%d", &n, &m)){
int ss[maxn], cnt = 0;
build(1, n, 1);
for(int i = 0; i < m; i++){
getchar();
scanf("%c", &op);
if(op == 'D'){
scanf("%d", &p);
ss[cnt++] = p;
upDate(p, 0, 1, n, 1);
}
else if(op == 'Q'){
scanf("%d", &p);
int res = query(p, 1, n, 1);
printf("%d\n", res);
}
else if(op == 'R'){
if(cnt > 0){
p = ss[--cnt];
upDate(p, 1, 1, n, 1);
}
}
}
}
return 0;
}
/*
20 100
D 8
D 12
Q 10
*/