线段树的区间合并基础题。
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 5e4 + 5;
int lx[MAX_N * 4], rx[MAX_N * 4], mx[MAX_N*4];
int n, q;
stack<int> s;
void init(int l, int r, int k) {
lx[k] = rx[k] = mx[k] = r - l;
if (r - l == 1) return;
init(l, (l + r) / 2, 2 * k + 1);
init((l + r) / 2,r, 2 * k + 2);
}
void add(int x, int l, int r, int k, int flag) {
if (x < l || r <= x) return;
if (r - l == 1) {
lx[k] = rx[k] = mx[k] = flag;
return;
}
int mid = (l + r) >> 1;
add(x, l, mid, 2 * k + 1, flag);
add(x, mid, r, 2 * k + 2, flag);
if (mx[2 * k + 1] == mid - l) lx[k] = mid - l + lx[2 * k + 2];
else lx[k] = lx[2 * k + 1];
if (mx[2 * k + 2] == r - mid) rx[k] = r - mid + rx[2 * k + 1];
else rx[k] = rx[2 * k + 2];
mx[k] = max(max(mx[2 * k + 1], mx[2 * k + 2]), rx[2 * k + 1] + lx[2 * k + 2]);
}
int query(int x, int l, int r, int k) {
if (x < l || r <= x) return 0;
if (r - l == 1 || mx[k] == r - l || mx[k] == 0) return mx[k];
int mid = (l + r) / 2;
int lm = mid - rx[2 * k + 1], rm = mid + lx[2 * k + 2];
if (lm <= x && x < rm) return rm - lm;
else return query(x, l, (l + r) / 2, 2 * k + 1) + query(x, (l + r) / 2, r, 2 * k + 2);
}
int main() {
while (~scanf("%d%d", &n, &q)) {
while (!s.empty()) s.pop();
init(0, n, 0);
char str[2];
for (int i = 0; i < q; i++) {
int a;
scanf("%s", str);
if (str[0] == 'D') {
scanf("%d", &a);
s.push(a);
add(a - 1, 0, n, 0, 0);
}
else if (str[0] == 'Q') {
scanf("%d", &a);
printf("%d\n",query(a - 1, 0, n, 0));
}
else {
a = s.top(); s.pop();
add(a - 1, 0, n, 0, 1);
}
}
}
}