题意:
。。。
思路:
类似 Hotel。。
不同的地方是,需要通过单点来得到包含它的空区间。
因为空区间一定会在某个节点分成两半,一半在左孩子,一半在右孩子。(空区间长度为1特例)
所以查询时加个判断就行了。
PS:set 可秒
const int N = 5e4;
#define lc o<<1
#define rc o<<1|1
struct node {
int l, r, m;
};
node tr[ (N<<2) + 100];
void upd(int o, int L, int R) {
tr[o].l = tr[lc].l;
if ( tr[lc].m == L ) tr[o].l = tr[lc].m + tr[rc].l;
tr[o].r = tr[rc].r;
if ( tr[rc].m == R ) tr[o].r = tr[rc].m + tr[lc].r;
tr[o].m = max ( max ( tr[lc].m, tr[rc].m ), tr[lc].r + tr[rc].l );
}
void build(int o, int l, int r) {
if ( l != r ) {
int m = (l + r) >> 1;
build(lc, l, m);
build(rc, m+1, r);
upd(o, m - l + 1, r - m);
} else {
tr[o] = (node) {1, 1, 1};
}
}
void modify(int o, int l, int r, int x, int v) {
if ( l == r ) {
tr[o] = (node) {v, v, v}; return;
}
int m = (l + r) >> 1;
if ( x <= m )
modify(lc, l, m, x, v);
else
modify(rc, m+1, r, x, v);
upd(o, m - l + 1, r - m);
}
int qres;
void query(int o, int l, int r, int x) {
if ( l == r ) {
qres += tr[o].m; return;
}
int m = (l + r) >> 1;
if ( x <= m ) {
if ( x >= m - tr[lc].r + 1 ) {
qres += tr[lc].r + tr[rc].l; return;
}
query(lc, l, m, x);
} else {
if ( x <= m + tr[rc].l ) {
qres += tr[lc].r + tr[rc].l; return;
}
query(rc, m + 1, r, x);
}
}
int n, m;
bool used[N+5];
void Del(int x) {
modify(1, 1, n, x, 0);
used[x] = 1;
}
void Res(int x) {
modify(1, 1, n, x, 1);
used[x] = 0;
}
int main() {
#ifdef _LOCA_ENV_
freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
while ( scanf("%d%d", &n, &m) != EOF ) {
memset(used, 0, sizeof(used));
stack<int> last;
build(1, 1, n);
rep(i, 1, m) {
char op; int x;
for (op = getchar(); op == ' ' || op == '\n'; op = getchar());
if ( op == 'D' ) {
scanf("%d", &x);
if ( !used[x] ) {
Del(x);
last.push(x);
}
} else if ( op == 'R' ) {
if ( !last.empty() ) {
Res(last.top());
last.pop();
}
} else if ( op == 'Q' ) {
scanf("%d", &x);
if ( used[x] ) puts("0");
else {
qres = 0;
query(1, 1, n, x);
printf("%d\n", qres);
}
} else throw runtime_error("...");
}
}
return 0;
}