题意是给你n个点,接下来有一些操作,包括删除某个点或者恢复某个删除的点,现在有一些询问,问包含某个点的连续区间的最大长度
思路:用线段树维护区间[l,r],ls表示区间内以l为左端点的连续区间的最大长度,rs表示区间内以r为右端点的连续区间的最大长度,ms表示区间内最大连续区间长度。更新操作时需要维护这三个变量。然后查询[l,r]内包含点pos的连续最大长度时,利用分治的思想,将区间分为[l,mid],[mid+1,r],如果pos<=mid,那么查询左区间,同时要观察左区间的rs是否包含pos,若包含,结果还需加上右区间的ls;当pos>mid时情况类似。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N=50005;
char s[5];
struct node
{
int ls,ms,rs;
}a[N<<2];
int temp[N];
void build(int l,int r,int rt)
{
a[rt].ls=a[rt].rs=a[rt].ms=r-l+1;
if(l==r)return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int pos,int v,int l,int r,int rt)
{
if(l==r)
{
a[rt].ls=a[rt].ms=a[rt].rs=v;
return;
}
int m=(l+r)>>1;
if(pos<=m)update(pos,v,lson);
else update(pos,v,rson);
a[rt].ls=a[rt<<1].ls;
a[rt].rs=a[rt<<1|1].rs;
a[rt].ms=max(max(a[rt<<1].ls,a[rt<<1|1].rs),a[rt<<1].rs+a[rt<<1|1].ls);
if(a[rt<<1].ls==m-l+1)
a[rt].ls+=a[rt<<1|1].ls;
if(a[rt<<1|1].rs==r-m)
a[rt].rs+=a[rt<<1].rs;
}
int query(int pos,int l,int r,int rt)
{
if(l==r||a[rt].ms==0||a[rt].ms==r-l+1)return a[rt].ms;
int m=(l+r)>>1;
if(pos<=m)
{
if(m-a[rt<<1].rs+1>pos)return query(pos,lson);
else return query(pos,lson)+query(m+1,rson);
}
else
{
if(m+a[rt<<1|1].ls<pos)return query(pos,rson);
else return query(pos,rson)+query(m,lson);
}
}
int main()
{
//freopen("a.txt","r",stdin);
int n,m;
while(~scanf("%d%d",&n,&m))
{
build(1,n,1);
int ct=0;
while(m--)
{
scanf("%s",s);
int pos;
if(s[0]=='D')
{
scanf("%d",&pos);
update(pos,0,1,n,1);
temp[++ct]=pos;
}
if(s[0]=='Q')
{
scanf("%d",&pos);
printf("%d\n",query(pos,1,n,1));
}
if(s[0]=='R')
{
update(temp[ct],1,1,n,1);
ct--;
}
}
}
return 0;
}