题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540
这个题目是个区间合并的模板题,但是有一点不同的是分两步查询思路很清晰;
这里有一个博客写的不错,我就不再赘述了;链接:http://blog.csdn.net/xingyeyongheng/article/details/11619461
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<algorithm>
#define LL long long
#define inf 1<<30
#define s(a,b) scanf("%d%d",&a,&b)
#define Clear(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=50015;
int n,m,a,b,ch;
int num[N]; // 该数组记录被损坏的村庄;
int ls[N<<2],rs[N<<2]; // 分别存左右端点起的最大长度;
void PushUp(int rt,int m)
{
ls[rt]=ls[rt<<1];
rs[rt]=rs[rt<<1|1];
if(ls[rt]==m-(m>>1)) ls[rt]+=ls[rt<<1|1]; // 左儿子区间最大长度为整个区间,需要拼接右儿子区间左端点起的最长长度;
if(rs[rt]==m>>1) rs[rt]+=rs[rt<<1]; // 右儿子区间最大长度为整个区间,同理;
}
void Build(int l,int r,int rt)
{
ls[rt]=rs[rt]=r-l+1; // 初始化为最长长度;
if(l!=r){
int mid=(l+r)>>1;
Build(l,mid,rt<<1);
Build(mid+1,r,rt<<1|1);
}
}
void Updata(int p,int v,int l,int r,int rt)
{
if(l==r){
ls[rt]=v;
rs[rt]=v;
return;
}
int mid=(l+r)>>1;
if(p<=mid) Updata(p,v,l,mid,rt<<1);
else Updata(p,v,mid+1,r,rt<<1|1);
PushUp(rt,r-l+1);
}
int QueryL(int L,int R,int l,int r,int rt) // 返回右边左区间最大长度;
{
if(L<=l&&r<=R) return ls[rt];
int mid=(l+r)>>1;
if(R<=mid) return QueryL(L,R,l,mid,rt<<1);
else if(L>mid) return QueryL(L,R,mid+1,r,rt<<1|1);
else{
int lans=QueryL(L,mid,l,mid,rt<<1);
int rans=QueryL(mid+1,R,mid+1,r,rt<<1|1);
if(lans==mid-L+1) return lans+rans;
else return lans;
}
}
int QueryR(int L,int R,int l,int r,int rt) // 返回左边右区间最大长度;
{
if(L<=l&&r<=R) return rs[rt];
int mid=(l+r)>>1;
if(R<=mid) return QueryR(L,R,l,mid,rt<<1);
else if(L>mid) return QueryR(L,R,mid+1,r,rt<<1|1);
else{
int lans=QueryR(L,mid,l,mid,rt<<1);
int rans=QueryR(mid+1,R,mid+1,r,rt<<1|1);
if(rans==R-mid) return lans+rans;
return rans;
}
}
int main()
{
//freopen("../../in.txt","r",stdin);
//freopen("../../out.txt","w",stdout);
while(~s(n,m)){
Build(1,n,1);
int top=0;
while(m--){
scanf(" %c",&ch);
if(ch=='D'){
scanf("%d",&a);
num[top++]=a;
Updata(a,0,1,n,1);
}else if(ch=='R'&&top>0){ // top>0说明还有被损坏的村庄;
int a=num[--top];
Updata(a,1,1,n,1);
}else if(ch=='Q'){
scanf("%d",&a);
int ans=QueryL(a,n,1,n,1)+QueryR(1,a,1,n,1);
printf("%d\n",ans>0?ans-1:0);
}
}
}
return 0;
}