题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540
题目大意:三种操作,D销毁一个城市,R复活最近摧毁的一个城市,Q询问x所在城市所在的连续存活城市长度。
题目思路:1表示存活,0表示摧毁,则求得就是x所在的1的长度。维护三个量,线段中最左边1的长度,线段中最右边1的长度,线段中最长的1的长度,分别用l1,r1,m1表示。所以更新时,大的段的最左边1的长度就是他的左半边的最左边1长度,如果左半边全是1的话,那么就是最左边长度加右半边的最左边1长度。最右同理。最大的量就是左半边和最右边m1取max,接着再跟左半边的最右边1长度+右半边的最左边1长度取max就是m1。然后是查询。查询的话如果x在mid的左边,判断他在不在左半边的最右连续1中,在的话要跟右半边的左半边1进行合并,不在就直接继续管左边。这里需要注意,return query(rt<<1,x)+query(rt<<1|1,mid+1);,后面返回的是mid+1,不是x了。
以下是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<math.h>
#include<stack>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
const ll MAXN = 5e4+5;
const ll MOD = 1e9+7;
char cmd[10];
stack<int>s;
struct node{
int l,r,l1,r1,m1;
}a[MAXN<<2];
void build(int rt,int l,int r){
a[rt].l=l,a[rt].r=r;
a[rt].l1=a[rt].r1=a[rt].m1=r-l+1;
if(l==r)return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void update(int rt,int x,int val){
if(a[rt].l == x && a[rt].r == x){
a[rt].l1 = a[rt].r1 = a[rt].m1 = val;
return;
}
int mid=(a[rt].l + a[rt].r)>>1;
if(x <= mid)update(rt<<1,x,val);
if(x > mid)update(rt<<1|1,x,val);
a[rt].l1 = a[rt<<1].l1 , a[rt].r1 = a[rt<<1|1].r1;
a[rt].m1 = max(a[rt<<1].m1, a[rt<<1|1].m1);
a[rt].m1=max(a[rt].m1,a[rt<<1].r1 + a[rt<<1|1].l1);
if(a[rt<<1].l1==a[rt<<1].r-a[rt<<1].l+1)a[rt].l1 += a[rt<<1|1].l1;
if(a[rt<<1|1].r1==a[rt<<1|1].r-a[rt<<1|1].l+1)a[rt].r1 += a[rt<<1].r1;
}
int query(int rt,int x){
if(a[rt].l==a[rt].r||a[rt].m1==0||a[rt].m1==a[rt].r-a[rt].l+1){
return a[rt].m1;
}
int mid=(a[rt].l+a[rt].r)>>1;
if(x<=mid){
if(a[rt<<1].r-a[rt<<1].r1 + 1 <= x)return query(rt<<1,x)+query(rt<<1|1,mid+1);
return query(rt<<1,x);
}
else{
if(a[rt<<1|1].l + a[rt<<1|1].l1 - 1 >= x)return query(rt<<1,mid)+query(rt<<1|1,x);
return query(rt<<1|1,x);
}
}
int main(){
int n,m,x;
while(~scanf("%d%d",&n,&m)){
while(!s.empty())s.pop();
build(1,1,n);
while(m--){
scanf("%s",cmd);
if(cmd[0]=='D'){
scanf("%d",&x);
update(1,x,0);
s.push(x);
}
if(cmd[0]=='R'){
int temp=s.top();
s.pop();
update(1,temp,1);
}
if(cmd[0]=='Q'){
scanf("%d",&x);
int ans=query(1,x);
printf("%d\n",ans);
}
}
}
return 0;
}