题目大意:给你N个点,相邻的点连线。现在有3种操作
D x:破坏和x相连的线
Q x:x和几个点相连
R:修复刚被破坏的点的连接

解题思路:刚破坏的点可以用一个栈来存储。现在的问题是,怎么求一个点和几个点相连
我们维护区间的三个值,从最左端往右的连续没有被破坏的点数量lsum,从最右端开始往左的连续的没有被破坏的点的数量rsum,区间内最长的连续的没有被破坏的点的数量tsum

询问的时候可以这样做,首先先判断一下该点所属的区间的tsum,如果tsum为0,表示这个区间内没有点连通,那么返回的就是0了,如果tsum == (r - l + 1)表示所有的点都被连接起来了,那么返回(r - l + 1)
如果都不是的话,判断一下该点属于左区间还是右区间
假设属于左区间,那就要判断一下,该点是否在左区间的rsum范围内,如果在该范围内,表示该点和mid相连,所以还得查询一下右区间,找寻和mid + 1相连的点的数量。如果不在rsum的范围内,直接递归查找下去
右区间的情况和左区间的情况类似

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
const int N = 50010 << 2;

int lsum[N], rsum[N], tsum[N], mark[N];
int n, m;
void build(int u, int l, int r) {
    lsum[u] = rsum[u] = tsum[u] = r - l + 1;
    mark[u] = -1;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
}

void Update(int u, int l, int r) {
    lsum[u] = rsum[u] = tsum[u] = mark[u] ? 0 : r - l + 1;
}

void PushDown(int u, int l, int r) {
    if (mark[u] == -1) return ;
    mark[u << 1] = mark[u << 1 | 1] = mark[u];
    mark[u] = -1;
    int mid = (l + r) >> 1;
    Update(u << 1, l, mid);
    Update(u << 1 | 1, mid + 1, r);
}

void PushUp(int u, int l, int r) {
    tsum[u] = max(max(tsum[u << 1], tsum[u << 1 | 1]), rsum[u << 1] + lsum[u << 1 | 1]);
    lsum[u] = lsum[u << 1];
    rsum[u] = rsum[u << 1 | 1];
    int mid = (l + r) >> 1;
    if (lsum[u] == mid - l + 1)
        lsum[u] += lsum[u << 1 | 1];
    if (rsum[u] == r - mid)
        rsum[u] += rsum[u << 1];
}

void Modify(int u, int l, int r, int pos, int c) {
    if (l == r) {
        mark[u] = c;
        Update(u, l, r);
        return ;
    }
    PushDown(u, l, r); 
    int mid = (l + r) >> 1;
    if (pos <= mid) Modify(u << 1, l, mid, pos, c);
    else Modify(u << 1 | 1, mid + 1, r, pos, c);
    PushUp(u, l, r);
}

int Query(int u, int l, int r, int pos) {
    if (l == r || tsum[u] == 0 || tsum[u] == r - l + 1) 
        return tsum[u];
    PushDown(u, l, r);
    int mid = (l + r) >> 1;
    if (pos <= mid) {
        int tmp = mid - rsum[u << 1] + 1;
        if (pos >= tmp) return Query(u << 1, l, mid, pos) + Query(u << 1 | 1, mid + 1, r, mid + 1);
        else return Query(u << 1, l, mid, pos);
    }
    else {
        int tmp = mid + lsum[u << 1 | 1];
        if (pos <= tmp) return Query(u << 1 | 1, mid + 1, r, pos) + Query(u << 1, l, mid, mid);
        else return Query(u << 1 | 1, mid + 1, r, pos);
    }
}

void solve() {
    stack<int> Stack;
    build(1, 1, n);
    char op[4];
    int pos;
    while (m--) {
        scanf("%s", op);
        if (op[0] == 'R') {
            if (Stack.empty()) continue;
            pos = Stack.top();
            Stack.pop();
            Modify(1, 1, n, pos, 0);
        }
        else if (op[0] == 'D') {
            scanf("%d", &pos);
            Stack.push(pos);
            Modify(1, 1, n, pos, 1);
        }
        else {
            scanf("%d", &pos);
            printf("%d\n", Query(1, 1, n, pos));
        }
    }
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF)  solve();
    return 0;
}