思路
先考虑暴力,当询问一个村庄时可以暴力向左找第一个被摧毁的点,再暴力向右找第一个被摧毁的点,两点之间的距离减一就是答案.直接暴力肯定会超时,所以我们可以考虑用线段树维护区间信息;查询的点为x,则x-n的最小值值减去1-x的最大值再减一即为答案.摧毁一个点就把那个点的最大值和最小值改为那个点的序号.重建用栈保存之前的信息即可.还有就是点信息的初始化,把最大值置为0,最小值置为1.
代码
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define ll __int64
//#define int ll
//typedef long long ll;
typedef unsigned long long ull;
const int MAXN=1e5+10;
const int MOD=2333;
const double eps=1e-6;
using namespace std;
//-------------------------------------------//
int a[MAXN],maxx[MAXN<<2],minx[MAXN<<2];
int n,m;
void pushup(int rt)
{
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
minx[rt]=min(minx[rt<<1],minx[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
minx[rt]=n+1;
maxx[rt]=0;
return;
}
int m=l+r>>1;
build(ls);
build(rs);
pushup(rt);
}
void updata(int pos,char op,int l,int r,int rt)
{
//cout<<l<<" "<<r<<endl;
if(l==r)
{
if(op=='D')maxx[rt]=minx[rt]=pos;
else maxx[rt]=0,minx[rt]=n+1;
return;
}
int m=l+r>>1;
if(m>=pos)updata(pos,op,ls);
if(m<pos)updata(pos,op,rs);
pushup(rt);
}
int query1(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return minx[rt];
int m=l+r>>1;
int res1=INF,res2=INF;
if(m>=L)res1=query1(L,R,ls);
if(m<R)res2=query1(L,R,rs);
return min(res1,res2);
}
int query2(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return maxx[rt];
int m=l+r>>1;
int res1=0,res2=0;
if(m>=L)res1=query2(L,R,ls);
if(m<R)res2=query2(L,R,rs);
return max(res1,res2);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
build(1,n,1);
stack<int> s;
while(m--)
{
char op;
int pos;
scanf(" %c",&op);
if(op!='R')
{
scanf("%d",&pos);
if(op=='D')s.push(pos),updata(pos,op,1,n,1);
else printf("%d\n",max(0,query1(pos,n,1,n,1)-query2(1,pos,1,n,1)-1));
}
else
{
updata(s.top(),op,1,n,1);
s.pop();
}
}
}
return 0;
}