LOJ # 535. "LibreOJ Round # 6" Fireworks (the largest sub-rectangle problem + + scan line segment tree)

https://loj.ac/problem/535

answer:

This is a classic feeling a little problem, I do not think ye.

Not reverse exchange is logarithmic.

Consider exchange \ (h [x] \) and \ (H [Y] \) .

To satisfy \ (H [the X-]> H [the y-] \) , otherwise there is no meaning.

Then reverse to reduce \ (2 * \ sum_ {x <z <y} h [x]> h [z]> h [y] \)

This is equivalent to the number of points rectangle problem: the \ ((x, h [x ]) \) is the top left corner, \ ((the y-, H [the y-]) \) is in the lower right corner of the rectangle points.

Noting that a top left corner \ ((x, h [x ]) \) if \ ((u, h [u ]) \) satisfies \ (u <x and h [u]> h [x ] \)

That \ ((u [u]) \, h) in \ ((x, h [x ]) \) the upper left corner, since the number of points to make up a rectangular footprint, it is selected from \ ((u, h [u ]) \) as the top-left corner than \ ((X, H [X]) \), .

Similarly to the lower right corner.

Possible upper left corner to meet \ (x \) when incremented, \ (H [the X-] \) decline.

Now consider each point \ (z \) , in \ (z \) point of the upper left corner is a range, the lower right corner the same way, this range can be half out.

Then adding into a rectangle, selecting the maximum value problem, the scanning line segment tree to +.

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int N = 3e5 + 5;

int n, h[N], p[N], q[N];
struct P {
    int x, y, f;
};
vector<P> d[N];
#define pb push_back

void Init() {
    scanf("%d", &n);
    fo(i, 1, n) scanf("%d", &h[i]);
    fo(i, 1, n) p[i] = max(p[i - 1], h[i]);
    q[n + 1] = 3e5 + 1; fd(i, n, 1) q[i] = min(q[i + 1], h[i]);
    fo(i, 1, n) {
        int x = 0, y = n + 1;
        for(int l = 1, r = i - 1; l <= r; ) {
            int m = l + r >> 1;
            if(p[m] < h[i]) x = m, l = m + 1; else r = m - 1;
        }
        for(int l = i + 1, r = n; l <= r; ) {
            int m = l + r >> 1;
            if(q[m] > h[i]) y = m, r = m - 1; else l = m + 1;
        }
        if(x + 1 <= i - 1 && i + 1 <= y - 1) {
            d[x + 1].pb((P) {i + 1, y - 1, 1});
            d[i].pb((P) {i + 1, y - 1, -1});
        }
    }
}

int t[N * 4], lz[N * 4];
int pl, pr, px;

#define i0 i + i
#define i1 i + i + 1
void pla(int i, int y) { t[i] += y, lz[i] += y;}
void down(int i) { if(lz[i]) pla(i0, lz[i]), pla(i1, lz[i]), lz[i] = 0;}
void add(int i, int x, int y) {
    if(y < pl || x > pr) return;
    if(x >= pl && y <= pr) {
        pla(i, px); return;
    }
    int m = x + y >> 1; down(i);
    add(i0, x, m); add(i1, m + 1, y);
    t[i] = max(t[i0], t[i1]);
}
#define low(x) ((x) & -(x))

ll ans, f[N];
void add(int x, int y) {
    for(; x <= 3e5; x += low(x)) f[x] += y;
}
ll sum(int x) {
    ll s = 0;
    for(; x; x -= low(x)) s += f[x];
    return s;
}

void Work() {
    fo(i, 1, n) {
        ff(j, 0, d[i].size()) {
            P v = d[i][j];
            pl = v.x, pr = v.y, px = v.f;
            add(1, 1, n);
        }
        ans = max(ans, (ll) t[1]);
    }
    ans = -2 * ans;
    fo(i, 1, n) {
        ans += sum(3e5) - sum(h[i]);
        add(h[i], 1);
    }
    pp("%lld\n", ans);
}

int main() {
    Init();
    Work();
}

Guess you like

Origin www.cnblogs.com/coldchair/p/12362067.html