1、题目大意:给你一个序列,有5种操作,都有什么呢。。。

1> 区间第k小 这个直接用二分+树套树做

2> 区间小于k的有多少 这个直接用树套树做

3> 单点修改 这个直接用树套树做

4> 区间内k的前驱 这个就是1和2操作的合并,就是查询k的排名,然后就是知道他的前驱的排名,然后第k小

5> 区间内k的后继 这个和4同理

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node{
    Node *ch[2];
    int num, cnt, v, r;
    bool operator < (const Node& rhs) const{
        return r < rhs.r;
    }
    inline int cmp(int x){
        if(x == v) return -1;
        if(x < v) return 0;
        return 1;
    }
    inline void maintain(){
        cnt = num;
        if(ch[0]) cnt += ch[0] -> cnt;
        if(ch[1]) cnt += ch[1] -> cnt;
        return;
    }
} ft[5000000], *root[400000];
int tot;
int a[100000];
inline void treap_rotate(Node* &o, int d){
    Node *k = o -> ch[d ^ 1];
    o -> ch[d ^ 1] = k  -> ch[d];
    k -> ch[d] = o;
    o -> maintain();
    k -> maintain();
    o = k;
    return;
}
inline void treap_insert(Node* &o, int value){
    if(!o){
        o = &ft[tot ++];
        o -> ch[0] = o -> ch[1] = NULL;
        o -> num = 1;
        o -> v = value;
        o -> r = rand();
    }
    else{
        int d = o -> cmp(value);
        if(d == -1){
            o -> num ++;
        }
        else{
            treap_insert(o -> ch[d], value);
            if(o -> ch[d] > o) treap_rotate(o, d ^ 1);
        }
    }
    o -> maintain();
}
inline void treap_remove(Node* &o, int value){
    if(!o) return;
    int d = o -> cmp(value);
    if(d == -1){
        if(o -> num > 1) o -> num --;
        else if(!o -> ch[0]) o = o -> ch[1];
        else if(!o -> ch[1]) o = o -> ch[0];
        else{
            int d2;
            if(o -> ch[0] > o -> ch[1]) d2 = 1;
            else d2 = 0;
            treap_rotate(o, d2);
            treap_remove(o -> ch[d2], value);
        }
    }
    else{
        treap_remove(o -> ch[d], value);
    }
    if(o) o -> maintain();
}
inline int treap_lessk(Node* &o, int k){
    if(!o) return 0;
    int d = o -> cmp(k);
    if(d == -1){
        int ret = o -> num;
        if(o -> ch[0]) ret += o -> ch[0] -> cnt;
        return ret;
    }
    else if(d == 0){
        return treap_lessk(o -> ch[d], k);
    }
    else{
        int ss = o -> num;
        if(o -> ch[0]) ss += o -> ch[0] -> cnt;
        return treap_lessk(o -> ch[d], k) + ss;
    }
}
inline int treap_find(Node* &o, int k){
    if(!o) return 0;
    int d = o -> cmp(k);
    if(d == -1) return o -> num;
    else return treap_find(o -> ch[d], k);
}
inline int segment_tree_find(int l, int r, int o, int x, int y, int k){
    if(x <= l && r <= y){
        return treap_find(root[o], k);
    }
    int mid = (l + r) / 2;
    int ret = 0;
    if(x <= mid) ret += segment_tree_find(l, mid, 2 * o, x, y, k);
    if(y > mid) ret += segment_tree_find(mid + 1, r, 2 * o + 1, x, y, k);
    return ret;
}
inline void segment_tree_add(int l, int r, int o, int x, int value){
    treap_remove(root[o], a[x]);
    treap_insert(root[o], value);
    if(l == r){
        a[x] = value;
        return;
    }
    int mid = (l + r) / 2;
    if(x <= mid) segment_tree_add(l, mid, 2 * o, x, value);
    else segment_tree_add(mid + 1, r, 2 * o + 1, x, value);
}
inline int segment_tree_query_lessk(int l, int r, int o, int x, int y, int k){
    if(x <= l && r <= y){
        return treap_lessk(root[o], k);
    }
    int mid = (l + r) / 2;
    int ret = 0;
    if(x <= mid) ret += segment_tree_query_lessk(l, mid, 2 * o, x, y, k);
    if(y > mid) ret += segment_tree_query_lessk(mid + 1, r, 2 * o + 1, x, y, k);
    return ret;
}
inline int segment_tree_query_NO_k(int l, int r, int o, int x, int y, int k, int n){
    int L = 0, R = 100000000;
    while(L < R){
        int mid = (L + R) / 2;
        if(segment_tree_query_lessk(1, n, 1, x, y, mid) < k) L = mid + 1;
        else R = mid;
    }
    return L;
}
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++){
        int x;
        scanf("%d", &x);
        segment_tree_add(1, n, 1, i, x);
    }
    for(int i = 1; i <= m; i ++){
        int op, x, y, z;
        scanf("%d", &op);
        if(op == 1){
            scanf("%d%d%d", &x, &y, &z);
            int ans = segment_tree_query_lessk(1, n, 1, x, y, z);
            ans -= segment_tree_find(1, n, 1, x, y, z);
            ans ++;
            printf("%d\n", ans);
        }
        else if(op == 2){
            scanf("%d%d%d", &x, &y, &z);
            int ans = segment_tree_query_NO_k(1, n, 1, x, y, z, n);
            printf("%d\n", ans);
        }
        else if(op == 3){
            scanf("%d%d", &x, &y);
            segment_tree_add(1, n, 1, x, y);
        }
        else if(op == 4){
            scanf("%d%d%d", &x, &y, &z);
            int k = segment_tree_query_lessk(1, n, 1, x, y, z);
            k -= segment_tree_find(1, n, 1, x, y, z);
            int ans = segment_tree_query_NO_k(1, n, 1, x, y, k, n);
            printf("%d\n", ans);
        }
        else{
            scanf("%d%d%d", &x, &y, &z);
            int k = segment_tree_query_lessk(1, n, 1, x, y, z);
            k ++;
            int ans = segment_tree_query_NO_k(1, n, 1, x, y, k, n);
            printf("%d\n", ans);
        }
    }
    return 0;
} 

BZOJ3196——二逼平衡树的更多相关文章

  1. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  2. bzoj3196 二逼平衡树 树状数组套线段树

    题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...

  3. bzoj3196 二逼平衡树 树套树(线段树套Treap)

    Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4697  Solved: 1798[Submit][Status][D ...

  4. bzoj3196 二逼平衡树

    题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...

  5. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  6. [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]

    题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...

  7. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  8. luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)

    带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...

  9. BZOJ3196:二逼平衡树(线段树套Splay)

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...

随机推荐

  1. System.currentTimeMillis()计算方式与时间的单位转换

    目录[-] 一.时间的单位转换 二.System.currentTimeMillis()计算方式 一.时间的单位转换 1秒=1000毫秒(ms) 1毫秒=1/1,000秒(s)1秒=1,000,000 ...

  2. centos 查看cpu个数、核数

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数 cat /proc/cpuinfo| ...

  3. scrapy3_ 安装指南

    安装指南 安装Scrapy 注解 请先阅读 平台安装指南. 下列的安装步骤假定您已经安装好下列程序: Python 2.7 Python Package: pip and setuptools. 现在 ...

  4. Java自定义异常类

    用户可以根据自己的需要定义自己的异常类,定义异常类只需要继承Exception类即可 //================================================= // Fi ...

  5. Android学习笔记——Handler(一)

    使用Handler管理线程(转) 步骤: 1. 申请一个Handler对象 Handler handler = new Handler(); 2. 创建一个线程 {继承Thread类或者实现Runna ...

  6. Servlet之Filter详解

    参考文献:http://www.cnblogs.com/zlbx/p/4888312.html Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程.为什么要引入过滤器呢?在平常访问网站的时 ...

  7. 总结CSS面试题目的考察点及常见布局问题整理

    整理网上流传的若干份面试题目,突发奇想,总结关于CSS面试题目的考察点,发现问题大多围绕几个属性和几种题目,水平有限,仅供参考. 写这个博文内心有种莫名奇妙的自我谴责感,实在不应该把面试层叠样式“应试 ...

  8. ecshop默认配置

    手机端 1.C, 系统默认所有配置 输出:print_r(C())

  9. C#:String.Format数字格式化输出

    int a = 12345678; //格式为sring输出//   Label1.Text = string.Format("asdfadsf{0}adsfasdf",a);// ...

  10. struts.xml框架

    1.首先在.jsp文件中<form action="/项目名称/login" method="post"> 2.然后浏览器会访问struts.xml ...