【BZOJ4491】我也不知道题目名字是什么(线段树)

Description

给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串。


Solution

线段树维护左边、中间、右边的最长不升/降子串,pushup时维护一下即可。


Code

/************************************************
 * Au: Hany01
 * Prob: bzoj4491
 * Email: [email protected]
 * Inst: Yali High School
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define x first
#define y second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read() {
    static int _, __; static char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

const int maxn = 5e4 + 5;

int n, a[maxn];

struct Item {
    int il, ir, im, dl, dr, dm, l, r;
}tr[maxn << 2];

#define mid ((l + r) >> 1)
#define lc (t << 1)
#define rc (lc | 1)

inline Item merge(Item L, Item R) {
    static Item M;
    M.l = L.l, M.r = R.r;
    M.il = L.il, M.ir = R.ir, M.dl = L.dl, M.dr = R.dr, M.im = max(L.im, R.im), M.dm = max(L.dm, R.dm);
    if (a[L.r] <= a[R.l]) {
        chkmax(M.im, L.ir + R.il);
        if (L.il == L.r - L.l + 1) M.il = L.il + R.il;
        if (R.ir == R.r - R.l + 1) M.ir = R.ir + L.ir;
    }
    if (a[L.r] >= a[R.l]) {
        chkmax(M.dm, L.dr + R.dl);
        if (L.dl == L.r - L.l + 1) M.dl = L.dl + R.dl;
        if (R.dr == R.r - R.l + 1) M.dr = R.dr + L.dr;
    }
    return M;
}

void build(int t, int l, int r) {
    if (l == r) {
        a[l] = read(), tr[t].l = l, tr[t].r = r,
        tr[t].il = tr[t].ir = tr[t].im = tr[t].dl = tr[t].dr = tr[t].dm = 1;
        return;
    }
    build(lc, l, mid), build(rc, mid + 1, r), tr[t] = merge(tr[lc], tr[rc]);
}

Item query(int t, int l, int r, int x, int y) {
    if (x <= l && r <= y) return tr[t];
    if (y <= mid) return query(lc, l, mid, x, y);
    if (x >  mid) return query(rc, mid + 1, r, x, y);
    return merge(query(lc, l, mid, x, y), query(rc, mid + 1, r, x, y));
}

int main()
{
#ifdef hany01
    freopen("bzoj4491.in", "r", stdin);
    freopen("bzoj4491.out", "w", stdout);
#endif

    n = read(), build(1, 1, n);
    for (static int m = read(), l, r; m --; ) {
        register Item t;
        l = read(), r = read(), t = query(1, 1, n, l, r), printf("%d\n", max(t.im, t.dm));
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/hhaannyyii/article/details/81349420