线段树求一个点所处区间的最大连续长度,用lsum记录区间的左连续长度,rsum记录区间的
右连续长度,查询时判断p点处于左子树还是右子树,然后计算左子树的右连续长度+右子树
的左连续长度的和。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 const int MAXN = 50050; int lsum[MAXN << 2], rsum[MAXN << 2]; int stack[MAXN]; int n, m; void build(int l, int r, int rt) { int mid = l + r >> 1; lsum[rt] = rsum[rt] = r - l + 1; if(l == r) return; build(lson); build(rson); } void PushUp(int l, int r, int rt) { int mid = l + r >> 1; lsum[rt] = lsum[rt << 1]; rsum[rt] = rsum[rt << 1 | 1]; if(lsum[rt << 1] == mid - l + 1) lsum[rt] += lsum[rt << 1 | 1]; if(rsum[rt << 1 | 1] == r - mid) rsum[rt] += rsum[rt << 1]; } void update(int c, int p, int l, int r, int rt) { int mid = l + r >> 1; if(p <= l && r <= p) { lsum[rt] = rsum[rt] = c; return; } if(p <= mid) update(c, p, lson); else update(c, p, rson); PushUp(l, r, rt); } int query(int p, int l, int r, int rt) { int mid = l + r >> 1; if(p <= l && r <= p) { return lsum[rt]; } if(p <= mid) { if(mid - rsum[rt << 1] + 1 <= p) //判断p所处的位置 { return rsum[rt << 1] + lsum[rt << 1 | 1]; } else return query(p, lson); } else { if(mid + 1 + lsum[rt << 1 | 1] - 1 >= p) { return rsum[rt << 1] + lsum[rt << 1 | 1]; } else return query(p, rson); } } void operation() { int top = 0, x; char op[5]; while(m --) { scanf("%s", op); if('D' == op[0]) { scanf("%d", &x); stack[++ top] = x; update(0, x, 1, n, 1); } else if('Q' == op[0]) { scanf("%d", &x); printf("%d\n", query(x, 1, n, 1)); } else { x = stack[top --]; update(1, x, 1, n, 1); } } } int main() { while(scanf("%d%d", &n, &m) == 2) { build(1, n, 1); operation(); } return 0; }