7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
1 0 2 4
#include <cstdio> #include <cstring> #include <iostream> #include <stack> #include <algorithm> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 using namespace std; const int maxn = 50000 + 10; int msum[maxn << 2], lsum[maxn << 2], rsum[maxn << 2]; void PushUp(int rt, int m) { lsum[rt] = lsum[rt << 1]; rsum[rt] = rsum[rt << 1 | 1]; //若左区间左连续满了,就还要考虑右区间的 if (lsum[rt << 1] == m - (m >> 1)) { lsum[rt] += lsum[rt << 1 | 1]; } //同上 if (rsum[rt << 1 | 1] == (m >> 1)) { rsum[rt] += rsum[rt << 1]; } //当前区间的最大连续长度在左右区间和跨区间的区间三个中找 msum[rt] = max(rsum[rt << 1] + lsum[rt << 1 | 1], max(msum[rt << 1], msum[rt << 1 | 1])); } void build(int l, int r, int rt) { msum[rt] = lsum[rt] = rsum[rt] = r - l + 1; if (l == r) return; int m = (l + r) >> 1; build(lson); build(rson); } //c为1的时候是恢复操作,c为0的时候是毁灭 void update(int x, int c, int l, int r, int rt) { if (l == r) { msum[rt] = lsum[rt] = rsum[rt] = c; return; } int m = (l + r) >> 1; if (x <= m) { update(x, c, lson); } else { update(x, c, rson); } PushUp(rt, r - l + 1); } int query(int x, int l, int r, int rt) { //到根节点或者区间最大连续长度为0,或者区间满直接返回 if (l == r || msum[rt] == 0 || msum[rt] == r - l + 1) { return msum[rt]; } int m = (l + r) >> 1; if (x <= m) { //查询的点在左区间的右连续区间范围内,就还要考虑右区间 if (x >= m - rsum[rt << 1] + 1) { return query(x, lson) + query(m + 1, rson); //注意是m + 1,即右区间左端点 } else { //否则只考虑左区间就行了 return query(x, lson); } } else { //同上 if (x <= (m + 1) + lsum[rt << 1 | 1] - 1) { return query(x, rson) + query(m, lson); //注意是m,即左区间右端点 } else { return query(x, rson); } } } int main() { int n, m, x; char op[2]; while (~scanf("%d%d", &n, &m)) { build(1, n, 1); stack<int> s; while (m--) { scanf("%s", op); if (op[0] == 'D') { scanf("%d", &x); s.push(x); update(x, 0, 1, n, 1); } else if (op[0] == 'Q') { scanf("%d", &x); printf("%d\n", query(x, 1, n, 1)); } else { if (!s.empty()) { x = s.top(); s.pop(); update(x, 1, 1, n, 1); } } } } return 0; }