Reconstruction of P4198 building in Luogu (line section tree)

meaning of the title

Title Link

Sol

Don't ask me why I sent it twice just to cheat traffic

The line tree method of this question is very wonderful

First of all, an obvious conclusion is that the position \ (i \) can be seen only if \ (\ frac {h} {K} < \ frac {h} {i}, K < i \)

Consider maintaining the visible points of the interval \ ([l, r] \).

Because there is only a single point of modification, you only need to consider how to merge two intervals

Maintain the maximum value of \ (\ frac {h {I} {I} \), and set it to \ (mx \)

First, the left child's answer can be added directly, considering the left child's contribution to the right child. If \ (MX {LS} > MX {RS} \), then the right child's answer is 0.

Otherwise, consider the contribution of the right child's left child. If \ (MX {RS {LS} > MX {LS} \), directly add the contribution of the right child's right child under the influence of the right child's left child (difference), recurse the right child's left child. Otherwise, the contribution of left child is 0, recursive right child

In fact, it's still good to write, complexity \ (O(nlog^2n) \)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, a[MAXN];
int sum[MAXN], ls[MAXN], rs[MAXN], ll[MAXN], rr[MAXN], tot, root;
double mx[MAXN];
int find(double lim, int k) {
    if(ll[k] == rr[k]) return mx[k] > lim;
    int mid = ll[k] + rr[k] >> 1;
    if(mx[ls[k]] > lim) return sum[k] - sum[ls[k]] + find(lim, ls[k]);
    else return find(lim, rs[k]);
}
void update(int k) {
    sum[k] = sum[ls[k]];
    mx[k] = max(mx[ls[k]], mx[rs[k]]);
    if(mx[ls[k]] > mx[rs[k]]) return ;
    sum[k] += find(mx[ls[k]], rs[k]);
}
void Modify(int &k, int l, int r, int p, double v) {
    if(!k) k = ++tot, ll[k] = l, rr[k] = r;
    if(l == r) {sum[k] = 1; mx[k] = v; return ;}
    int mid = l + r >> 1;
    if(p <= mid) Modify(ls[k], l, mid, p, v);
    else Modify(rs[k], mid + 1, r, p, v);
    update(k);
}
signed main() {
    N = read(); M = read();
    for(int i = 1; i <= M; i++) {
        int x = read(), y = read();
        Modify(root, 1, N, x, (double) y / x);
        printf("%d\n", sum[root]);
    }
    return 0;
}
/*
3 4
2 4
3 6
1 1000000000
1 1
*/

Tags: C++

Posted on Mon, 02 Dec 2019 17:46:56 -0500 by jreed2132