HDU 1540 Tunnel Warfare

需要用线段树维护区间的3个变量:

区间最长的:[左连续前缀、右连续后缀、最大连续子区间] 的元素个数

其中红线左侧的是第m个元素,右侧是m+1个元素。

更新完左右子树想要pushUp操作的时候,父亲的左前缀必然是左子的前缀,若是左子树满了,则左连续可能还要加上右子树的左前缀。同理,父亲的右后缀必然是右子的后缀,若是右子都连续,那么还要加上左子的后缀。

查询的时候,若是位置p在左子的“橙色“部分,即后缀中,那么结果应当是左子中的连续部分+(m+1)(即m的下一个元素)在右子的连续部分,同理p在右子的紫色部分时,要考虑加上左子的后缀部分。

代码:

// #include <bits/stdc++.h>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
using namespace std;

#define ll long long
#define mst(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for (ll i = (a); i < (b); ++i)
const int inf = 0x3f3f3f3f, maxN = 5e4 + 7;
int N, M, T;
int stk[maxN];

#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define lch rt << 1
#define rch rt << 1 | 1

// 最长左连续前缀 右后缀 区间最大连续子区间
int lm[maxN << 2], rm[maxN << 2], mm[maxN << 2];

void init(int l, int r, int rt) {
    lm[rt] = rm[rt] = mm[rt] = r - l + 1;
    if (l == r)
        return;
    int m = (l + r) >> 1;
    init(lson);
    init(rson);
}

void update(int p, int x, int l, int r, int rt) {
    if (l == r) {
        lm[rt] = rm[rt] = mm[rt] = x;
        return;
    }
    int m = (l + r) >> 1;
    if (p <= m)
        update(p, x, lson);
    else
        update(p, x, rson);

    lm[rt] = lm[lch];
    rm[rt] = rm[rch];
    mm[rt] = max(max(lm[lch], rm[rch]), lm[rch] + rm[lch]);
    if (lm[lch] == m - l + 1)
        lm[rt] += lm[rch];
    if (rm[rch] == r - m)
        rm[rt] += rm[lch];
}

int query(int p, int l, int r, int rt) {
    if (mm[rt] == r - l + 1 || mm[rt] == 0 || l == r)
        return mm[rt];
    int m = (l + r) >> 1;
    if (p <= m) {
        if (p >= m - rm[lch] + 1)
            return query(p, lson) + query(m + 1, rson);
        else
            return query(p, lson);
    } else {
        if (p <= m + lm[rch])
            return query(p, rson) + query(m, lson);
        else
            return query(p, rson);
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
#endif
    while (~scanf("%d%d", &N, &M)) {
        char op[10];
        int a;
        int idx = 0;
        init(1, N, 1);
        rep(i, 0, M) {
            scanf("%s", op);
            if (op[0] == 'R') {
                update(stk[--idx], 1, 1, N, 1);
                continue;
            }
            scanf("%d", &a);
            if (op[0] == 'Q') {
                printf("%d\n", query(a, 1, N, 1));
            } else {
                update(a, 0, 1, N, 1);
                stk[idx++] = a;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rosebud/p/9126016.html