虽然这题在线段树的专题里面,,然而我并不觉得需要用线段树
维护一个set和stack,set里面的数字表示被摧毁的村庄节点,stack里面存放的是被摧毁的村庄节点
初始化,将0和n+1插入到set中,表示0和n+1村庄已被摧毁,,起到边界的作用
D t 将t插入到set中,将t压入栈中,表示t已经被摧毁
R 将栈的栈顶取出,并弹出,在set中删除对应的村庄编号
Q t 在set中找到<=t的元素记为L,在set中找到>=t的元素记为R,如果L或者R的某一个等于t,表示t已经存在于set中了,也就是t村庄已经被摧毁了,就输出0,否则输出R-L-1,因为L表示t左边最近被摧毁的村庄,R表示t右边最近被摧毁的村庄,那么R-L-1就表示中间连续没有被摧毁的数量,就是答案了
所以STL大法秒杀此题
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, int> PLI;
const int MX = 1e3 + 5;
const int INF = 0x3f3f3f3f;
set<int>G;
stack<int>Last;
int main() {
int n, Q;
while(~scanf("%d%d", &n, &Q)) {
G.clear();
while(!Last.empty()) Last.pop();
G.insert(0);
G.insert(n + 1);
while(Q--) {
char op[5]; int x;
scanf("%s", op);
if(op[0] == 'D') {
scanf("%d", &x);
G.insert(x);
Last.push(x);
} else if(op[0] == 'Q') {
scanf("%d", &x);
int L = *(--G.upper_bound(x));
int R = *(G.lower_bound(x));
if(L == x || R == x) {
printf("0\n");
} else {
printf("%d\n", R - L - 1);
}
} else {
int t = Last.top();
Last.pop();
G.erase(t);
}
}
}
return 0;
}