线段树.
三种操作:D x->摧毁村庄x,
R -> 修复被毁时间最近的那个村庄
Q x->查询包括x的最大连续的村庄
也就是查询某个区间的连续值吧,但麻烦的是只知道这个区间包含了x.
如果x在左子树,并且左子树的rsum包含了x,那么说明右子树有一段也是我们所求的,
右子树同理.
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
inline int input()
{
int ret=0;
char c;
c=getchar();
while(c<'0'||c>'9')
{
if(c=='D') return -1;
if(c=='R') return -2;
if(c=='Q') return -3;
c=getchar();
}
while(c>='0'&&c<='9')
{
ret=ret*10+c-'0';
c=getchar();
}
return ret;
}
#define N 50010
int n,m,stack[N],cnt,op,x;
struct node
{
int l,r;
int lsum,rsum,msum;
}root[N*6];
inline void Push_up(int t)
{
int ll=root[t*2].r-root[t*2].l+1;
int lr=root[t*2+1].r-root[t*2+1].l+1;
root[t].lsum=root[t*2].lsum+(root[t*2].lsum==ll?root[t*2+1].lsum:0);
root[t].rsum=root[t*2+1].rsum+(root[t*2+1].rsum==lr?root[t*2].rsum:0);
int p=max(root[t*2].msum,root[t*2+1].msum);
root[t].msum=max(p,root[t*2].rsum+root[t*2+1].lsum);
}
inline void build(int t,int x,int y)
{
root[t].l=x;
root[t].r=y;
root[t].lsum=root[t].rsum=root[t].msum=y-x+1;
if(x==y) return;
int m=(x+y)>>1;
build(t*2,x,m);
build(t*2+1,m+1,y);
}
inline void Modefiy(int t,int x,int z)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==x)
{
root[t].lsum=root[t].rsum=root[t].msum=z;
return;
}
int m=(l+r)>>1;
if(x<=m) Modefiy(t*2,x,z);
else if(x>m) Modefiy(t*2+1,x,z);
Push_up(t);
}
inline int query(int t,int x)
{
int l=root[t].l,r=root[t].r;
int m=(l+r)>>1;
if(l==r)
return root[t].msum;
if(root[t].msum==0)
return 0;
if(root[t].msum==r-l+1)
return root[t].msum;
if(x<=m)
{
if(x>=root[t*2].r-root[t*2].rsum+1)
return query(t*2,x)+query(t*2+1,m+1);
else
return query(t*2,x);
}
else
{
if(x<=root[t*2+1].l+root[t*2+1].lsum-1)
return query(t*2+1,x)+query(t*2,m);
else
return query(t*2+1,x);
}
}
int main()
{
while(~scanf("%d",&n))
{
m=input();
build(1,1,n);
cnt=0;
for(int i=1;i<=m;i++)
{
op=input();
if(op==-1)
{
x=input();
stack[cnt++]=x;
Modefiy(1,x,0);
}
else if(op==-2)
{
x=stack[--cnt];
Modefiy(1,x,1);
}
else
{
x=input();
printf("%d\n",query(1,x));
}
}
}
return 0;
}