zoukankan      html  css  js  c++  java
  • [BZOJ 3196]Tyvj 1730 二逼平衡树

    Description

    题库链接

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

    1. 查询 (k) 在区间内的排名;
    2. 查询区间内排名为 (k) 的值;
    3. 修改某一位值上的数值;
    4. 查询 (k) 在区间内的前驱(前驱定义为小于 (x) ,且最大的数);
    5. 查询 (k) 在区间内的后继(后继定义为大于 (x) ,且最小的数)

    (1leq n,mleq 50000)

    Solution

    我也不知道为什么让我参考题目标题...并没有写平衡树...

    树状数组套线段树。常用的套路。

    查询 (x) 的排名就是查询 ([1, x-1]) 内有多少个数 (+1) ;求区间 (k) 小可以二分值域;

    对于前驱后继,我们可以先求出原数的排名,再 (pm 1) ,求 (k) 小。

    时间复杂度 (O(nlog_2^3 n)) ,空间复杂度 (O(nlog_2^2 n))

    Code

    //It is made by Awson on 2018.2.27
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int INF = ~0u>>1;
    const int N = 1e5;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
     
    int n, m, a[N+5], b[N+5], tot;
    struct operate {int o, l, r, k; }opt[N+5];
    struct Tree_set_tree {
        int root[N+5], ch[N*80+5][2], key[N*80+5], pos;
        int cpynode(int o) {++pos, ch[pos][0] = ch[o][0], ch[pos][1] = ch[o][1], key[pos] = key[o]; return pos; }
        void insert(int &o, int l, int r, int loc, int val) {
        if (o == 0) o = cpynode(o); key[o] += val;
        if (l == r) return; int mid = (l+r)>>1;
        if (loc <= mid) insert(ch[o][0], l, mid, loc, val);
        else insert(ch[o][1], mid+1, r, loc, val);
        }
        int query(int o, int l, int r, int a, int b) {
        if ((a <= l && r <= b) || o == 0) return key[o];
        int c1 = 0, c2 = 0, mid = (l+r)>>1;
        if (a <= mid) c1 = query(ch[o][0], l, mid, a, b);
        if (b > mid) c2 = query(ch[o][1], mid+1, r, a, b);
        return c1+c2;
        }
        void add(int o, int loc, int val) {for (; o <= n; o += lowbit(o)) insert(root[o], 1, tot, loc, val); }
        int query(int o, int a, int b) {
        int ans = 0; if (a > b) return 0; 
        for (; o; o -= lowbit(o)) ans += query(root[o], 1, tot, a, b);
        return ans;
        }
    }T;
     
    int kth(int l, int r, int k) {
        int L = 1, R = tot, ans = tot;
        while (L <= R) {
        int mid = (L+R)>>1;
        int tmp = T.query(r, 1, mid)-T.query(l-1, 1, mid);
        if (tmp < k) L = mid+1; else R = mid-1, ans = mid; 
        }
        return b[ans];
    }
    void work() {
        read(n), read(m);
        for (int i = 1; i <= n; i++) read(a[i]), b[++tot] = a[i];
        for (int i = 1; i <= m; i++) {
        read(opt[i].o);
        if (opt[i].o == 3) read(opt[i].l), read(opt[i].k), b[++tot] = opt[i].k;
        else if (opt[i].o == 2) read(opt[i].l), read(opt[i].r), read(opt[i].k);
        else read(opt[i].l), read(opt[i].r), read(opt[i].k), b[++tot] = opt[i].k;
        }
        sort(b+1, b+tot+1); tot = unique(b+1, b+tot+1)-b-1;
        for (int i = 1; i <= n; i++) T.add(i, lower_bound(b+1, b+tot+1, a[i])-b, 1);
        for (int i = 1; i <= m; i++) {
        if (opt[i].o == 1) {
            int loc = lower_bound(b+1, b+tot+1, opt[i].k)-b;
            writeln(T.query(opt[i].r, 1, loc-1)-T.query(opt[i].l-1, 1, loc-1)+1);
        }else if (opt[i].o == 2) writeln(kth(opt[i].l, opt[i].r, opt[i].k));
        else if (opt[i].o == 3) {
            T.add(opt[i].l, lower_bound(b+1, b+tot+1, a[opt[i].l])-b, -1);
            T.add(opt[i].l, lower_bound(b+1, b+tot+1, a[opt[i].l] = opt[i].k)-b, 1);
        }else if (opt[i].o == 4) {
            int loc = lower_bound(b+1, b+tot+1, opt[i].k)-b;
            writeln(kth(opt[i].l, opt[i].r, T.query(opt[i].r, 1, loc-1)-T.query(opt[i].l-1, 1, loc-1)));
        }else if (opt[i].o == 5) {
            int loc = lower_bound(b+1, b+tot+1, opt[i].k)-b;
            writeln(kth(opt[i].l, opt[i].r, T.query(opt[i].r, 1, loc)-T.query(opt[i].l-1, 1, loc)+1));
        }
        }
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    URAL 2046 A
    URAL 2056 Scholarship 水题
    Codeforces Gym 100286I iSharp 水题
    Codeforces Gym H. Hell on the Markets 贪心
    Codeforces Gym 100286G Giant Screen 水题
    Codeforces Gym 100286B Blind Walk DFS
    Codeforces Gym 100286F Problem F. Fibonacci System 数位DP
    Codeforces Gym 100286A. Aerodynamics 计算几何 求二维凸包面积
    Codeforces Gym 100418K Cards 暴力打表
    Codeforces Gym 100418J Lucky tickets 数位DP
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8477761.html
Copyright © 2011-2022 走看看