当a村庄存在时,用二分找到1到a-1内核a村庄相连的最大村庄数目,再找到a+1,到n内和a村庄相连的最大村庄数目
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#include <stack>
#define maxn 50005
using namespace std;
typedef long long ll;
int num[maxn<<2], vis[maxn];
stack<int> sta;
void Update(int n, int l, int r, int s, int d){
if(l == r){
num[n] = d;
return ;
}
int mid = (l + r) >> 1;
if(s <= mid)
Update(n<<1, l, mid, s, d);
else
Update(n<<1|1, mid+1, r, s, d);
num[n] = num[n<<1] && num[n<<1|1];
}
void Query(int n, int l, int r, int L, int R, int &s){
if(l == L && R == r){
s = s && num[n];
return ;
}
int mid = (l + r) >> 1;
if(R <= mid)
Query(n<<1, l, mid, L, R, s);
else if(L > mid)
Query(n<<1|1, mid+1, r, L, R, s);
else{
Query(n<<1, l, mid, L, mid, s);
Query(n<<1|1, mid+1, r, mid+1, R, s);
}
}
int main(){
// freopen("in.txt", "r", stdin);
int n, m;
while(scanf("%d%d ", &n, &m) == 2){
while(!sta.empty())
sta.pop();
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= (n<<2); i++)
num[i] = 1;
char ch;
int a;
while(m--){
scanf("%c ", &ch);
if(ch == 'D'){
scanf("%d ", &a);
vis[a] = 1;
Update(1, 1, n, a, 0);
sta.push(a);
}
else if(ch == 'R'){
int b = sta.top();
sta.pop();
vis[b] = 0;
Update(1, 1, n, b, 1);
}
else if(ch == 'Q'){
scanf("%d ", &a);
if(vis[a]){
printf("%d\n", 0);
continue;
}
int cnt = 1;
int l = 1, r = a;
if(r != 1){
while(l < r){
int s = 1;
int mid = (l + r) >> 1;
Query(1, 1, n, mid, a-1, s);
if(s)
r = mid;
else
l = mid+1;
}
cnt += a - l;
}
if(l != n){
l = a + 1;
r = n + 1;
while(l < r){
int s = 1;
int mid = (l + r) >> 1;
Query(1, 1, n, a+1, mid, s);
if(s)
l = mid + 1;
else
r = mid;
}
cnt += l - a - 1;
}
printf("%d\n", cnt);
}
}
}
return 0;
}