[Gym101821B] LIS vs. LDS

Portal

Just find a LIS and LDS, found at most one element intersect.

Drawing out of the fold line, found in the above case, two fold lines intersect at a vertex.

Then we want to find the solution of the case is two fold lines intersection between two certain elements. (Not in the post can be regarded as \ ((0, 1) \) or \ ((n, n + 1 ) \) cross between a)

Then enumerate the intersection position between the two elements which, taking into account the size of the intersection between which two integers.

Position assumed intersection is \ (P \ in (I, I +. 1) \) , size \ (X \ in (J, J +. 1) \) , it must be in \ ([1, i] \ ) and flipped around \ ([i + 1, n ] \) within each end element selected from not more than a \ (J \) of the LIS and the last element is not smaller than a (j + 1 \) \ of LDS. In \ (X \) establishing the segment tree index, each index at the maintenance position corresponding to the intersection and the maximum value of four.

Since when the value is four symmetrical, only consider this intersection position, in \ ([1, i] \ ) in a take no more than \ (J \) of the LIS changes. Consider seeking LIS normal process, so that \ (F_i \) of length \ (I \) at the end of the LIS minimum elements, the \ (F_i \) does not exceed \ (X \) a \ (I \) th number is the answer. Adding an element at the end of \ (a \) when will the smallest \ (f_k \ geq a \) becomes \ (a \) , which is to \ ([a, f_k] \ ) of this section range of answers \ (+ 1 \) . Similarly the rest position, and the pre-change element value.

More details of the code, it may just write me in trouble ......

This is the way the magic question on a revision of OJ, no solution should construct a cancer too ...... (

#include <bits/stdc++.h>
#define R register
#define mp make_pair
#define ll long long
#define pii pair<int, int>
using namespace std;
const int N = 510000;

int n, p[N], fr[N], gr[N], fbc[N], gbc[N], f[N], g[N], a[N], fl[N], gl[N], ans1[N], ans2[N];

struct segmentTree {
//
#define mid ((lt[k] + rt[k]) >> 1)
#define l (k << 1)
#define r (k << 1 | 1)
static const int K = N << 2;

int lt[K], rt[K], maxV[K], add[K], maxLb[K];

inline void init(int n, int *a) {
    lt[1] = 1, rt[1] = n, build(1, a);
    return;
}

inline void update(int k) {
    if (maxV[r] > maxV[l]) maxV[k] = maxV[r], maxLb[k] = maxLb[r];
    else maxV[k] = maxV[l], maxLb[k] = maxLb[l];
    return;
}

void build(int k, int *a) {
    if (lt[k] == rt[k]) {
        maxV[k] = a[lt[k]], maxLb[k] = lt[k];
        return;
    }
    lt[l] = lt[k], rt[l] = mid, lt[r] = mid + 1, rt[r] = rt[k];
    return build(l, a), build(r, a), update(k);
}

void modify(int k, int x, int y, int w) {
    if (lt[k] >= x && rt[k] <= y) {
        add[k] += w, maxV[k] += w;
        return;
    }
    pushdown(k);
    if (x <= mid) modify(l, x, y, w);
    if (y > mid) modify(r, x, y, w);
    return update(k);
}

inline void pushdown(int k) {
    if (add[k]) {
        modify(l, lt[k], rt[k], add[k]);
        modify(r, lt[k], rt[k], add[k]);
        add[k] = 0;
    }
    return;
}

inline pii query() {
    return mp(maxV[1], maxLb[1]);
}

#undef mid
#undef l
#undef r
//
} seg;

template <class T>
inline void read(T &x) {
    x = 0;
    char ch = getchar(), w = 0;
    while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    x = w ? -x : x;
    return;
}

int main() {
    read(n);
    for (R int i = 1; i <= n; ++i) read(p[i]), f[i] = g[i] = n + 1;
    int n1 = 0, n2 = 0;
    for (R int i = n; i; --i) {
        fr[i] = lower_bound(f + 1, f + 1 + n1, p[i]) - f;
        gr[i] = lower_bound(g + 1, g + 1 + n2, n + 1 - p[i]) - g;
        n1 = max(n1, fr[i]), n2 = max(n2, gr[i]);
        fbc[i] = f[fr[i]], gbc[i] = g[gr[i]];
        f[fr[i]] = p[i], g[gr[i]] = n + 1 - p[i];
    }
    f[n + 1] = n + 1;
    for (R int i = 1, tl1 = 1, tl2 = n; i <= n + 1; ++i) {
        while (f[tl1] < i) ++tl1;
        while (g[tl2] > n + 1 - i) --tl2;
        a[i] = tl1 + tl2 - 1;
    }
    for (R int i = 1; i <= n + 1; ++i) f[i] = g[i] = n + 1;
    seg.init(n + 1, a);
    int pos = 0;
    pii ans = seg.query(), tmp;
    // x >= i -> n+1-x <= n+1-i -> y <= n+1-i -> i <= n+1-y
    for (R int i = 1; i <= n; ++i) {
        fl[i] = lower_bound(f + 1, f + 1 + n, p[i]) - f;
        gl[i] = lower_bound(g + 1, g + 1 + n, n + 1 - p[i]) - g;
        if (f[fl[i]] < fbc[i]) seg.modify(1, f[fl[i]] + 1, fbc[i], -1);
        else if (f[fl[i]] > fbc[i]) seg.modify(1, fbc[i] + 1, f[fl[i]], 1);
        if (g[gl[i]] < gbc[i]) seg.modify(1, n + 2 - gbc[i], n + 1 - g[gl[i]], -1);
        else if (g[gl[i]] > gbc[i]) seg.modify(1, n + 2 - g[gl[i]], n + 1 - gbc[i], 1);
        tmp = seg.query(), f[fl[i]] = p[i], g[gl[i]] = n + 1 - p[i];
        if (ans < tmp) pos = i, ans = tmp;
    }
    if (ans.first != n1 + n2) return printf("IMPOSSIBLE\n"), 0;
    for (R int i = 1; i <= n; ++i) f[i] = n + 1, g[i] = 0;
    for (R int i = 1; i <= pos; ++i)
        f[fl[i]] = p[i], g[gl[i]] = p[i];
    int kl = 0, kr = 0;
    while (kl < n && f[kl + 1] < ans.second) ++kl;
    while (kr < n && g[kr + 1] >= ans.second) ++kr;
    for (R int i = pos, tl = kl, tr = kr; i; --i) {
        if (fl[i] == tl) ans1[tl] = i, --tl;
        if (gl[i] == tr) ans2[n1 - tr + 1] = i, --tr;
    }
    for (R int i = pos + 1, tl = n2 - kl, tr = n1 - kr; i <= n; ++i) {
        if (fr[i] == tr) ans2[tr] = i, --tr;
        if (gr[i] == tl) ans1[n2 - tl + 1] = i, --tl;
    }
    printf("%d\n", n2);
    for (R int i = 1; i <= n2; ++i) printf("%d ", ans1[i]);
    printf("\n%d\n", n1);
    reverse(ans2 + 1, ans2 + n1 + 1);
    for (R int i = 1; i <= n1; ++i) printf("%d ", ans2[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/suwakow/p/12364651.html