• Codeforces 484E Sign on Fence(是持久的段树+二分法)


    题目链接:Codeforces 484E Sign on Fence

    题目大意:给定给一个序列,每一个位置有一个值,表示高度,如今有若干查询,每次查询l,r,w,表示在区间l,r中,

    连续最长长度大于w的最大高度为多少。

    解题思路:可持久化线段树维护区间合并,前端时间碰到一题可持久化字典树,就去查了一下相关论文,大概知道了是

    什么东西。

    将高度依照从大到小的顺序排序,然后每次插入一个位置,线段树维护最长连续区间,由于插入是依照从大到小的顺

    序,所以每次的线段树中的连续最大长度都是满足高度大于等于当前新插入的height值。对于每次查询,二分高度,因

    为高度肯定是在已有的高度中,所以仅仅接二分下表就可以。

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1e6 + 5;
    typedef pair<int,int> pii;
    struct Node {
        int lc, rc, lp, rp, L, R, S;
        int length() {
            return rp - lp + 1;
        }
    }nd[maxn << 2];
    
    int N, sz, root[maxn];
    pii blo[maxn];
    
    inline int newNode() {
        return sz++;
    }
    
    inline void pushup(int u) {
        int lcid = nd[u].lc, rcid = nd[u].rc;
        nd[u].L = nd[lcid].L + (nd[lcid].L == nd[lcid].length() ? nd[rcid].L : 0);
        nd[u].R = nd[rcid].R + (nd[rcid].R == nd[rcid].length() ? nd[lcid].R : 0);
        nd[u].S = max(nd[lcid].R + nd[rcid].L, max(nd[lcid].S, nd[rcid].S));
    }
    
    inline Node merge(Node a, Node b) {
        Node u;
        u.lp = a.lp; u.rp = b.rp;
        u.L = a.L + (a.L == a.length() ? b.L : 0);
        u.R = b.R + (b.R == b.length() ? a.R : 0);
        u.S = max(a.R + b.L, max(a.S, b.S));
        return u;
    }
    
    void build(int& u, int l, int r) {
        if (u == 0) u = newNode();
        nd[u] = (Node){0, 0, l, r, 0, 0, 0};
    
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        build(nd[u].lc, l, mid);
        build(nd[u].rc, mid +1, r);
        pushup(u);
    }
    
    int insert(int u, int x) {
        int k = newNode();
        nd[k] = nd[u];
    
        if (nd[k].lp == x && x == nd[k].rp) {
            nd[k].S = nd[k].L = nd[k].R = 1;
            return k;
        }
    
        int mid = (nd[k].lp + nd[k].rp) >> 1;
        if (x <= mid)
            nd[k].lc = insert(nd[k].lc, x);
        else
            nd[k].rc = insert(nd[k].rc, x);
        pushup(k);
        return k;
    }
    
    Node query(int u, int l, int r) {
        if (l <= nd[u].lp && nd[u].rp <= r)
            return nd[u];
    
        int mid = (nd[u].lp + nd[u].rp) >> 1;
        if (r <= mid)
            return query(nd[u].lc, l, r);
        else if (l > mid)
            return query(nd[u].rc, l, r);
        else {
            Node ll = query(nd[u].lc, l, r);
            Node rr = query(nd[u].rc, l, r);
            return merge(ll, rr);
        }
    }
    
    inline bool cmp (const pii& a, const pii& b) {
        return a.first > b.first;
    }
    
    void init () {
        sz = 1;
        scanf("%d", &N);
    
        for (int i = 1; i <= N; i++) {
            scanf("%d", &blo[i].first);
            blo[i].second = i;
        }
        sort(blo + 1, blo + 1 + N, cmp);
        build(root[0], 1, N);
        for (int i = 1; i <= N; i++)
            root[i] = insert(root[i-1], blo[i].second);
    }
    
    int main () {
        init();
    
        int q, l, r, w;
        scanf("%d", &q);
        while (q--) {
            scanf("%d%d%d", &l, &r, &w);
            int L = 1, R = N;
            while (L < R) {
                int mid = (L + R) >> 1;
                if (query(root[mid], l, r).S >= w)
                    R = mid;
                else
                    L = mid + 1;
            }
            printf("%d
    ", blo[L].first);
        }
        return 0;
    }
  • 相关阅读:
    任意钝角三角形都可以分割为7个锐角三角形
    科场的胜者
    VBA按区导出电脑字库区位码
    A macro to get all interior colorindex has been used in thisworkbook
    和菜鸟一起学linux总线驱动之初识spi总线协议
    Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析
    和菜鸟一起学android4.0.3源码之vibrator振动器移植心得
    opengl_NeNe 第九课,移动图像代码.vs 2010_express OPENGL 2.0
    和菜鸟一起学linux总线驱动之初识USB设备描述符
    和菜鸟一起学OK6410之熟悉内核源码
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4558615.html
Copyright © 2020-2023  润新知