• Solution 「洛谷 P4198」楼房重建


    \(\mathcal{Description}\)

      Link.

      给定点集 \(\{P_n\}\)\(P_i=(i,h_i)\)\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后求出 \((0,0)\cup\{P_n\}\) 的下凸壳大小(输出时 \(-1\))。

      \(n,m\le10^5\)\(h_i\ge0\)

    \(\mathcal{Solution}\)

      令 \(k_i=\frac{h_i}{i}\),我们相当于要维护 \(\{k_n\}\) 中从 \(k_1\) 开始的最长贪心上升子序列 (LGIS?)。

      这是一个动态维护 LGIS 的常见 trick:建一棵序列线段树,对于结点 \(u\),维护区间最大值 \(x_u\) 以及以左区间的最大值为起始的,在右区间中的 LGIS 长度(不包括左区间最大值,故实际值为长度 \(-1\))。

      维护过程,需要支持形如“在 \(u\) 区间内,仅考虑不小于 \(x\) 的值,LGIS 长度”的查询,利用已维护信息可以 \(\mathcal O(\log n)\) 树上查询解决,所以每次标记上传是 \(\mathcal O(\log n)\) 的,一次修改即 \(\mathcal O(\log^2 n)\),总复杂度为 \(\mathcal O(m\log^2n)\)

    \(\mathcal{Code}\)

    /*+Rainybunny+*/
    
    #include <bits/stdc++.h>
    
    #define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
    #define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
    
    const int MAXN = 1e5;
    const double EPS = 1e-7;
    int n, m, val[MAXN + 5];
    
    inline double dabs(const double u) { return u < 0 ? -u : u; }
    inline double dmax(const double u, const double v) { return u < v ? v : u; }
    inline int dcmp(const double u) { return dabs(u) < EPS ? 0 : u < 0 ? -1 : 1; }
    
    #define DR const int u, const int l, const int r
    #define SR 1, 1, n
    struct SegmentTree {
        double mx[MAXN << 2];
        int lgis[MAXN << 2];
    
        inline int calc(DR, const double x) {
            if (l == r) return dcmp(val[l] - x * l) == 1;
            int mid = l + r >> 1;
            if (~dcmp(mx[u << 1] - x)) return calc(u << 1, l, mid, x) + lgis[u];
            return calc(u << 1 | 1, mid + 1, r, x);
        }
    
        inline void pushup(DR) {
            mx[u] = dmax(mx[u << 1], mx[u << 1 | 1]);
            if (l != r) lgis[u] = calc(u << 1 | 1, l + r + 2 >> 1, r, mx[u << 1]);
        }
    
        inline void modify(DR, const int x, const int v) {
            if (l == r) return val[l] = v, mx[u] = 1. * val[l] / l, void();
            int mid = l + r >> 1;
            if (x <= mid) modify(u << 1, l, mid, x, v);
            else modify(u << 1 | 1, mid + 1, r, x, v);
            pushup(u, l, r);
        }
    } sgt;
    
    int main() {
        std::ios::sync_with_stdio(false), std::cin.tie(0);
    
        std::cin >> n >> m;
        rep (i, 1, m) {
            int x, y; std::cin >> x >> y;
            sgt.modify(SR, x, y), std::cout << sgt.calc(SR, 0.) << '\n';
        }
        return 0;
    }
    
    
  • 相关阅读:
    构建可视化基础——集成SVG
    构建可视化基础——使用HTML Canvas
    【目录】LeetCode Java实现
    【目录】数据结构与算法
    【目录】《剑指Offer》Java实现
    【LeetCode】102. Binary Tree Level Order Traversal
    【LeetCode】145. Binary Tree Postorder Traversal
    【LeetCode】144. Binary Tree Preorder Traversal
    【LeetCode】230. Kth Smallest Element in a BST
    【LeetCode】94. Binary Tree Inorder Traversal
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15556836.html
Copyright © 2020-2023  润新知