题意简述
给定一个长度为 n ( < = 5 e 4 ) n(<=5e4) n(<=5e4)的 01 01 01序列,一开始都是 1 1 1。支持三种操作:
- 修改某一个位置为 0 0 0
- 撤销上一次修改
- 询问包含某个位置的最长的连续的 1 1 1的个数。
思路
m u l t i s e t multiset multiset 维护位置,二分得到左右,相减即珂。
实现注意点
- 左右边界。左是 u p p e r b o u n d − 1 upperbound - 1 upperbound−1 ,右是 l o w e r b o u n d lowerbound lowerbound 。
- 关于撤销的操作:用一个栈维护删除的位置,每一次撤销就是取栈顶。(我是用 v e c t o r vector vector实现的栈,因为我不是很会用 s t a c k stack stack,不要在意)
代码
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
multiset<int> S;
multiset<int>::iterator it;
vector<int> D;
void Erase1(int x)
{
it=S.find(x);
S.erase(it);
}
int n,m;
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Input_Soviet()
{
R1(n),R1(m);
S.insert(0);
S.insert(n+1);
F(i,1,m)
{
char o[4];scanf("%s",o);
if (o[0]=='D')
{
int x;R1(x);
S.insert(x);
D.push_back(x);
}
if (o[0]=='R')
{
int last=*(D.end()-1);
if (S.find(last)!=S.end())
{
Erase1(last);
D.pop_back();
}
}
if (o[0]=='Q')
{
int x;R1(x);
it=S.upper_bound(x);it--;
int ll=*it;
int rr=*(S.lower_bound(x));
printf("%d\n",max(rr-ll-1,0));
}
}
}
#define Flan void
Flan IsMyWife()
{
Input_Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}