• [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;
    }
  • 相关阅读:
    Asp.Net细节性问题技巧精萃
    存储过程(Stored Procedure)及应用
    合并datagrid中内容相同的单元格
    .net 2.0 下发送邮件的方式
    ADO.NET2.0的十大新特性
    sql server 中各个系统表的作用
    DataGrid一些文章的索引,方便查找
    ASP.NET中 WebControls 命名规则
    SQL Server应用程序中的高级SQL注入[转]
    数据操作例子
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8477761.html
Copyright © 2020-2023  润新知