zoukankan      html  css  js  c++  java
  • 【整体二分】【P3834】 【模板】可持久化线段树 1(主席树)

    Description

    给定一个长度为 (n) 的序列, (m) 次操作静态查询区间第 (k)

    Input

    第一行是 (n,m)

    下一行描述这个序列

    下面 (m) 行描述操作

    Output

    每个查询输出一行一个数代表答案

    Hint

    (1~leq~n,~m~leq~2~ imes~10^5)

    值域为 ([-1e9,~1e9])

    Solution

    考虑整体二分。

    将操作和序列全部离线,混在一起操作,在每层中,如果一个插入操作插入的数大于 mid,则压入右边的vector,否则压入左边的vector,这样即可保证在每一层整个序列的插入操作只被操作 (1) 次。用树状数组维护不大于 mid 的插入点,插入点个数不小于 (k) 的查询压入左侧,否则 (k~-=~ ext{压入点个数}) ,压入右侧即可。

    注意一个区间内没有操作的时候要剪枝,否则复杂度会加上值域。

    总复杂度 (O((n + m)~log^2 m))

    Code

    // luogu-judger-enable-o2
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #ifdef ONLINE_JUDGE
    #define freopen(a, b, c)
    #endif
    
    typedef long long int ll;
    
    namespace IPT {
        const int L = 1000000;
        char buf[L], *front=buf, *end=buf;
        char GetChar() {
            if (front == end) {
                end = buf + fread(front = buf, 1, L, stdin);
                if (front == end) return -1;
            }
            return *(front++);
        }
    }
    
    template <typename T>
    inline void qr(T &x) {
        char ch = IPT::GetChar(), lst = ' ';
        while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
        while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
        if (lst == '-') x = -x;
    }
    
    namespace OPT {
        char buf[120];
    }
    
    template <typename T>
    inline void qw(T x, const char aft, const bool pt) {
        if (x < 0) {x = -x, putchar('-');}
        int top=0;
        do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
        while (top) putchar(OPT::buf[top--]);
        if (pt) putchar(aft);
    }
    
    const int maxn = 200010;
    const int INF = 1000000010;
    
    struct OP {
        int l, r, k, id;
    };
    std::vector<OP> Q;
    
    int n, m;
    int ans[maxn], tree[maxn];
    
    int lowbit(int);
    int query(int);
    void update(int, const int);
    void divide(int, int, std::vector<OP>&);
    
    int main() {
        freopen("1.in", "r", stdin);
        qr(n); qr(m);
        for (int i = 1, x; i <= n; ++i) {
            x = 0; qr(x); Q.push_back({-1, 0, x, i});
        }
        for (int i = 1, a, b, c; i <= m; ++i) {
            a = b = c = 0; qr(a); qr(b); qr(c);
            Q.push_back({a, b, c, i});
        }
        divide(-INF, INF, Q);
        for (int i = 1; i <= m; ++i) qw(ans[i], '
    ', true);
        return 0;
    }
    
    void divide(int l, int r, std::vector<OP> &v) {
        if (!v.size()) return;
        if (l == r) {
            for (auto i : v) if (i.l != -1) ans[i.id] = l;
            return;
        }
        std::vector<OP>ldown, rdown;
        int mid = (l + r) >> 1;
        for (auto i : v) {
            if (i.l == -1) {
                if (i.k <= mid) {
                    update(i.id, 1);
                    ldown.push_back(i);
                } else rdown.push_back(i);
            }
        }
        for (auto i : v) {
            if (i.l != -1) {
                int k = query(i.r) - query(i.l - 1);
                if ((k) >= i.k) ldown.push_back(i);
                else {
                    i.k -= k; rdown.push_back(i);
                }
            }
        }
        for (auto i : ldown) {
            if (i.l == -1) update(i.id, -1);
        }
        divide(l, mid, ldown);
        divide(mid + 1, r, rdown);
    }
    
    inline int lowbit(int x) {return x & -x;}
    
    void update(int x, const int v) {
        while (x <= n) {
            tree[x] += v;
            x += lowbit(x);
        }
    }
    
    int query(int x) {
        int _ret = 0;
        while (x) {
            _ret += tree[x];
            x -= lowbit(x);
        }
        return _ret;
    }
    
  • 相关阅读:
    PAT 1006 Sign In and Sign Out
    PAT 1004. Counting Leaves
    JavaEE开发环境安装
    NoSql数据库探讨
    maven的配置
    VMWARE 下使用 32位 Ubuntu Linux ,不能给它分配超过3.5G 内存?
    XCODE 4.3 WITH NO GCC?
    在苹果虚拟机上跑 ROR —— Ruby on Rails On Vmware OSX 10.7.3
    推荐一首让人疯狂的好歌《Pumped Up Kicks》。好吧,顺便测下博客园可以写点无关技术的帖子吗?
    RUBY元编程学习之”编写你的第一种领域专属语言“
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10430542.html
Copyright © 2011-2022 走看看