zoukankan      html  css  js  c++  java
  • CF765F Souvenirs 离线+线段树+主席树

    $ color{#0066ff}{ 题目描述 }$

    A县旁,连绵着一条长度为 n 的山脉,这条山脉由 n 座山峰组成,第 i 座山
    峰的高度为 ai。作为著名的旅游县城,每天来到山脉游玩的旅客络绎不绝。但当
    游客们去过了第一座山之后,就必须要先下山,再上第二座山。这实在是件很麻
    烦的事,于是人们计划在山峰之间修建一些桥梁。
    修建桥梁是件很麻烦的事。因为如果两座山峰的高度差太大的话,再在这两
    座之间修建桥梁就显得有些不合适了。设计者们给出了 m 个计划,每个计划会
    从区间([l,r]) 中选择两座山峰,搭建桥梁。为了方便建设,他们会选择高度差最
    小的一组进行施工。他们想知道,这个最小的高度差是多少。

    (color{#0066ff}{输入格式})

    第丬行一个整数 n 表示山脉的长度。
    第二行 n 个整数 ai,表示每个山峰的高度。
    第三行一个整数 m 表示计划桥梁修建的数量。
    接下来的 m 行,每行两个整数l, r,表示将在区间 ([l, r]) 内修建仺座桥梁。

    (color{#0066ff}{输出格式})

    共 m 行。每行一个整数表示桥梁的构小高度差。

    (color{#0066ff}{输入样例})

    8
    3 1 4 1 5 9 2 6
    4
    1 8
    1 3
    4 8
    5 7
    

    (color{#0066ff}{输出样例})

    0
    1
    1
    3
    

    (color{#0066ff}{数据范围与提示})

    $ 2<=n<=10^{5} ,0<=a_{i}<=10^{9} 1<=m<=3*10^5$

    (color{#0066ff}{题解})

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
        char ch; LL x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
        return x * f;
    }
    const int inf = 0x7fffffff;
    const int maxn = 1e6 + 10;
    struct SGT {
    protected:
        struct node {
            int l, r;
            node *ch[2];
            int val, min;
            node(int l = 0, int r = 0, int val = inf, int min = inf): l(l), r(r), val(val), min(min) { ch[0] = ch[1] = NULL; }
            int mid() { return (l + r) >> 1; }
            void trn(int v) { min = std::min(min, v), val = std::min(val, v); }
            void dwn() {
                if(min == inf) return;
                ch[0]->trn(min), ch[1]->trn(min);
                min = inf;
            }
            void upd() { val = std::min(ch[0]->val, ch[1]->val); }
        }*root, pool[maxn * 4], *tail;
        void build(node *&o, int l, int r) {
            o = new(tail++) node(l, r);
            if(l == r) return;
            build(o->ch[0], l, o->mid());
            build(o->ch[1], o->mid() + 1, r);
        }
        void lazy(node *o, int l, int r, int val) {
            if(l > r) return;
            if(l <= o->l && o->r <= r) return o->trn(val);
            o->dwn();
            if(l <= o->mid()) lazy(o->ch[0], l, r, val);
            if(r > o->mid()) lazy(o->ch[1], l, r, val);
            o->upd();
        }
    public:
        SGT() { root = NULL; }
        void init(int n) { tail = pool; build(root, 1, n); }
        int query(int pos) {
            node *o = root;
            while(o->l != o->r) o->dwn(), o = o->ch[pos > o->mid()];
            return o->val;
        }
        void lazy(int l, int r, int val) {
            lazy(root, l, r, val); 
        }
    }s;
    struct node {
        node *ch[2];
        int pos, num;
        node(int pos = 0, int num = 0): pos(pos), num(num) { ch[0] = ch[1] = NULL; }
        void upd() { pos = std::max(ch[0]->pos, ch[1]->pos); }
    }*root[maxn], pool[maxn * 8], *tail = pool;
    struct question {
        int l, r, id;
        friend bool operator < (const question &a, const question &b) {
            return a.r < b.r; 
        }
    }e[maxn];
    int ans[maxn];
    void init() {
        root[0] = new node();
        root[0]->ch[0] = root[0]->ch[1] = root[0];
    }
    int n, m, a[maxn];
    void add(node *&o, node *lst, int l, int r, int pos, int id) {
        o = new(tail++) node(); *o = *lst, o->num++;
        if(l == r) return (void)(o->pos = id);
        int mid = (l + r) >> 1;
        if(pos <= mid) add(o->ch[0], lst->ch[0], l, mid, pos, id);
        else add(o->ch[1], lst->ch[1], mid + 1, r, pos, id);
        o->upd();
    }
    int query(node *o, int l, int r, int ql, int qr) {
        if(ql > qr) return -1;
        if(!o->num) return -1;
        if(ql <= l && r <= qr) return o->pos;
        int mid = (l + r) >> 1, ans = -1;
        if(ql <= mid) ans = std::max(ans, query(o->ch[0], l, mid, ql, qr));
        if(qr > mid) ans = std::max(ans, query(o->ch[1], mid + 1, r, ql, qr));
        return ans;
    }
    int main() {
        s.init(n = in()), init();
        for(int i = 1; i <= n; i++) add(root[i], root[i - 1], 1, 1e9, a[i] = in(), i);
        int m = in();
        for(int i = 1; i <= m; i++) e[i].l = in(), e[i].r = in(), e[i].id = i;
        std::sort(e + 1, e + m + 1);
        int now = 1;
        for(int i = 1; i <= n; i++) {
            int nowpos = query(root[i - 1], 1, 1e9, a[i], 1e9);
            while(~nowpos) {
                s.lazy(1, nowpos, a[nowpos] - a[i]);
                nowpos = query(root[nowpos - 1], 1, 1e9, a[i], ((a[i] + a[nowpos]) / 2));
            }
            while(now <= m && e[now].r == i) {
                ans[e[now].id] = s.query(e[now].l);
                now++;
            }
        }
        s.init(n);
        now = 1;
        for(int i = 1; i <= n; i++) {
            int nowpos = query(root[i - 1], 1, 1e9, 1, a[i] - 1);
            while(~nowpos) {
                s.lazy(1, nowpos, a[i] - a[nowpos]);
                nowpos = query(root[nowpos - 1], 1, 1e9, ((a[i] + a[nowpos]) / 2), a[i] - 1);
            }
            while(now <= m && e[now].r == i) {
                ans[e[now].id] = std::min(ans[e[now].id], s.query(e[now].l));
                now++;
            }
        }
        for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
        return 0;
    }
    /*
    11
    3 1 4 1 5 9 2 6 5 3 5
    5
    1 3
    1 8
    5 7
    6 8
    10 11
    */
    
  • 相关阅读:
    远程连接redis服务
    redis的安装以及启动
    Easyui学习之右键菜单easyui-menu
    富文本编辑器KindEditor的使用
    zookeeper启动失败解决方法
    在TortoiseSVN使用clean up
    kettle性能优化
    idea快捷键
    Spring Cloud服务网关 Zuul Filter使用
    添加路由
  • 原文地址:https://www.cnblogs.com/olinr/p/10608934.html
Copyright © 2011-2022 走看看