题意

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

  1. 查询k在区间内的排名

  2. 查询区间内排名为k的值

  3. 修改某一位值上的数值

  4. 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)

  5. 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)

注意上面两条要求和tyvj或者bzoj不一样,请注意

说明

时空限制:2s,128M

\(n,m \leq 5\cdot {10}^4\)

保证有序序列所有值在任何时刻满足$ [0, {10} ^8]$

分析

模板题。

树状数组套权值线段树,时空复杂度\(O((n+m) \log_2^2n)\)

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
#define lowbit(x) (x&-x)
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;
using std::vector;
vector<int> vs;

co int N=5e4+1,LG=120;
int c[N],n,m;
struct quiz{
    int opt,l,r,k;
}q[N];
// Tree Tao Tree
namespace T{
    // Interval Tree
    int L[N*LG],R[N*LG],sum[N*LG];
    int tot,root[N];
    int rank(vector<int>&x,int l,int r,int p){
        if(l==r) return 1;
        int m=(l+r)/2;
        if(p<=m){
            for(int i=0;i<x.size();++i)
                x[i]=x[i]<0?-L[-x[i]]:L[x[i]];
            return rank(x,l,m,p);
        }
        else{
            int s=0;
            for(int i=0;i<x.size();++i){
                x[i]<0?s-=sum[L[-x[i]]]:s+=sum[L[x[i]]];
                x[i]=x[i]<0?-R[-x[i]]:R[x[i]];
            }
            return s+rank(x,m+1,r,p);
        }
    }
    int kth(vector<int>&x,int l,int r,int k){
        if(l==r) return l;
        int s=0;
        for(int i=0;i<x.size();++i)
            x[i]<0?s-=sum[L[-x[i]]]:s+=sum[L[x[i]]];
        int m=(l+r)/2;
        if(s>=k){
            for(int i=0;i<x.size();++i)
                x[i]=x[i]<0?-L[-x[i]]:L[x[i]];
            return kth(x,l,m,k);
        }
        else{
            for(int i=0;i<x.size();++i)
                x[i]=x[i]<0?-R[-x[i]]:R[x[i]];
            return kth(x,m+1,r,k-s);
        }
    }
    void change(int&x,int l,int r,int p,int d){
        if(!x) x=++tot;
        sum[x]+=d;
        if(l==r) return;
        int m=(l+r)/2;
        if(p<=m) change(L[x],l,m,p,d);
        else change(R[x],m+1,r,p,d);
    }
    int precessor(vector<int>&x,int l,int r,int p){
        if(p==1) return -1;
        vector<int>y;
        int k=rank(y=x,l,r,p);
        if(k==1) return -1;
        return kth(y=x,l,r,k-1);
    }
    int successor(vector<int>&x,int l,int r,int p){
        if(p==vs.size()) return -1;
        vector<int>y;
        int k=rank(y=x,l,r,p+1)-1,s=0; // edit 1: reuse rank
        for(int i=0;i<x.size();++i)
            x[i]<0?s-=sum[-x[i]]:s+=sum[x[i]];
        if(k==s) return -1;
        return kth(y=x,l,r,k+1);
    }
    // Binaru Index Tree
    int rank(int l,int r,int v){
        vector<int> roots;
        for(int i=r;i;i-=lowbit(i))
            roots.push_back(root[i]);
        for(int i=l-1;i;i-=lowbit(i))
            roots.push_back(-root[i]);
        return rank(roots,1,vs.size(),v);
    }
    int kth(int l,int r,int k){
        vector<int> roots;
        for(int i=r;i;i-=lowbit(i))
            roots.push_back(root[i]);
        for(int i=l-1;i;i-=lowbit(i))
            roots.push_back(-root[i]);
        return kth(roots,1,vs.size(),k);
    }
    void change(int p,int v){
        for(int i=p;i<=n;i+=lowbit(i)){
            change(root[i],1,vs.size(),c[p],-1); // edit 1:c[p]
            change(root[i],1,vs.size(),v,1);
        }
        c[p]=v;
    }
    int precessor(int l,int r,int v){
        vector<int> roots;
        for(int i=r;i;i-=lowbit(i))
            roots.push_back(root[i]);
        for(int i=l-1;i;i-=lowbit(i))
            roots.push_back(-root[i]);
        return precessor(roots,1,vs.size(),v);
    }
    int successor(int l,int r,int v){
        vector<int> roots;
        for(int i=r;i;i-=lowbit(i))
            roots.push_back(root[i]);
        for(int i=l-1;i;i-=lowbit(i))
            roots.push_back(-root[i]);
        return successor(roots,1,vs.size(),v);
    }
}

int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n),read(m);
    for(int i=1;i<=n;++i)
        vs.push_back(read(c[i]));
    for(int i=1;i<=m;++i){
        read(q[i].opt);
        if(q[i].opt!=3){
            read(q[i].l),read(q[i].r),read(q[i].k);
            if(q[i].opt!=2) vs.push_back(q[i].k);
        }
        else read(q[i].l),vs.push_back(read(q[i].k));
    }
    sort(vs.begin(),vs.end()),vs.erase(unique(vs.begin(),vs.end()),vs.end());
    for(int i=1;i<=n;++i){
        c[i]=lower_bound(vs.begin(),vs.end(),c[i])-vs.begin()+1;
        for(int j=i;j<=n;j+=lowbit(j)) // insert
            T::change(T::root[j],1,vs.size(),c[i],1);
    }
    for(int i=1;i<=m;++i){
        if(q[i].opt!=2) q[i].k=lower_bound(vs.begin(),vs.end(),q[i].k)-vs.begin()+1; // edit 2: only operator 3
        if(q[i].opt==1) printf("%d\n",T::rank(q[i].l,q[i].r,q[i].k));
        else if(q[i].opt==2) printf("%d\n",vs[T::kth(q[i].l,q[i].r,q[i].k)-1]);
        else if(q[i].opt==3) T::change(q[i].l,q[i].k);
        else if(q[i].opt==4){
            int re=T::precessor(q[i].l,q[i].r,q[i].k);
            if(re==-1) puts("-2147483647");
            else printf("%d\n",vs[re-1]);
        }
        else if(q[i].opt==5){
            int re=T::successor(q[i].l,q[i].r,q[i].k);
            if(re==-1) puts("2147483647");
            else printf("%d\n",vs[re-1]);
        }
    }
    return 0;
}

LG3380 3380 【模板】二逼平衡树(树套树)的更多相关文章

  1. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  2. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  3. BZOJ3196 & 洛谷3380:二逼平衡树——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3196 https://www.luogu.org/problemnew/show/P3380 (题 ...

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

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

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

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

  6. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  7. [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

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

  8. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  9. ZJOI2013 K大数查询 和 LG3380【模板】二逼平衡树(树套树)

    K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c:如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的 ...

  10. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

随机推荐

  1. article标准用法

    article代表一个在文档.页面或者网站中自成一体的内容 其目的是为了让开或重用 譬如论坛的帖子.博客的文章.一片用户的评论.一个互动的widget小工具 article 会有一个标题(通常在hea ...

  2. 20145219 《Java程序设计》第07周学习总结

    20145219 <Java程序设计>第07周学习总结 教材学习内容总结 认识时间与日期 时间的度量 1.格林威治时间(GMT):通过观察太阳而得,因为地球公转轨道为椭圆形且速度不一,本身 ...

  3. Cisco、HUAWEI、H3c、Firewall等设备配置snmp

    配置HUAWEI交换机S1720.S2700.S5700.S6720等型号设备的snmp v3配置 注:此配置来源自官方配置文档 操作步骤 配置交换机的接口IP地址,使其和网管站之间路由可达 (图1) ...

  4. jQ&js给label

    <strong>当前角色:</strong><label id="lblRoleName" style="margin-bottom: 0p ...

  5. FckEditor 配置手册中文教程详细说明

    http://www.jb51.net/article/17965.htm 首先,FCKEDITOR的性能是非常好的,用户只需很少的时间就可以载入 FCKEDITOR所需文件.对于其他在线编辑器来说, ...

  6. BZOJ4455/UOJ185 [Zjoi2016]小星星

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  7. Pandas数据结构

    Pandas处理以下三个数据结构 - 系列(Series) 数据帧(DataFrame) 面板(Panel) 这些数据结构构建在Numpy数组之上,这意味着它们很快. 维数和描述 考虑这些数据结构的最 ...

  8. scala学习手记27 - 下划线与参数

    在Scala里,下划线(_)可以表示函数值的参数.如果某个参数在函数里仅使用一次,就可以用下划线表示.每次在函数里用下划线,都表示随后的参数. val arr = Array(1, 2, 3, 4, ...

  9. git常用操作 配置用户信息、拉取项目、提交代码、分支操作、版本回退...

    git常用操作 配置用户信息.拉取项目.提交代码.分支操作.版本回退... /********git 配置用户信息************/ git config --global user.name ...

  10. ToggleButton开关状态按钮控件

    ToggleButton开关状态按钮控件 一.简介 1. 2.ToggleButton类结构 父类是CompoundButton,引包的时候注意下 二.ToggleButton开关状态按钮控件使用方法 ...