题目大意:

网址:https://www.luogu.org/problemnew/show/2617
给定一个序列a[1]、a[2]、...、a[N],完成M个操作,操作有两种:
[1]Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
[2]C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
数据范围: \(1≤n≤10000,1≤m≤10000\)

解法:带修改的主席树:

原本的主席树是维护了一个线段树前缀。
那么前缀有没有想到什么东西? 树状数组\(Bits\)是不是很 ...... ?
那么现在,我们用树状数组套主席树,不就可以实现带修改的可持久化了吗。
具体来说 \(T[1]维护rt[1]\) , \(T[2]维护rt[1]、rt[2]\) , \(T[3]维护rt[3]\) ......
就与树状数组是一样的。
那么现在,两个具体的操作:

修改:

修改需要修改\(logN\)棵主席树,将涉及修改节点的\(log\)个主席树先删后加点即可。
具体来说,修改x位置的,则要修改:for(x; x; x -= (x&-x))Update(rt[x]);

查询:

考虑一下树状数组的查询,是用到了两个前缀相减的方法。
那么这里也是一样的,查询\([L,R]\)就是\([1,R]\)的值减去\([1,(L-1)]\)的值。
具体来说,对于\([L,R]\)区间对应的主席树,每个点的sum值为:
\[Sum[ro] = ∑sum[ro[u]] - ∑sum[ro[v]];u∈[1,R],v∈[1,L-1]\]
那么以查询第区间第\(k\)大为例子,直接将\(k\)与节点的\(Sum\)值比较即可。

总复杂度:

时间复杂度:\(O(NLog^2N)\) , 空间复杂度\(O(NLog^2N)\)

两个去重、二分的函数:

Unique去重函数:

对于a[1]、a[2]、....、a[N],去重函数为:
\[Length = Unique(a+1,a+N+1) - a - 1;\]
Unique函数返回的是 去重后后面第一个空位置,所以要长度减1。
去重完的序列即为a[1]、a[2]、....、a[Length];

Lower_Bound二分函数:

对于序列a[1]、a[2]、....、a[N],查找<=x的最接近数的序列位置,为:
k = lower_bound(a+1,a+N+1,x) - oder;
low_bound返回的是那个值的地址,应该要与第0个位置相减得到其确切的位置。

具体实现代码:

#include<bits/stdc++.h>
#define RG register
#define IL inline
#define maxn 200005
using namespace std;

int N,M,Q,cntl,cntr,lg;
struct Ques{int l,r,k;}qs[maxn];
int rt[2*maxn],ls[20*maxn],rs[20*maxn],sum[20*maxn],tpl[maxn],tpr[maxn];
int a[maxn],oder[2*maxn],cnt;

void Update(int &ro,int l,int r,int ps,int chg){
    if(!ro)ro = ++cnt;
    sum[ro] += chg;
    if(l == r)return;
    RG int mid = (l+r)>>1;
    if(ps <= mid)Update(ls[ro],l,mid,ps,chg);
    else Update(rs[ro],mid+1,r,ps,chg);
}

IL void Modify(RG int ps,RG int chg){
    RG int k = lower_bound(oder+1,oder+lg+1,a[ps]) - oder;
    for(RG int i = ps; i <= N; i += (i&-i))
        Update(rt[i],1,lg,k,chg);
}

int Query(int l,int r,int k){
    if(l == r)return l;
    RG int mid = (l+r)>>1,Sum = 0;
    for(RG int i = 1; i <= cntl; i ++)Sum -= sum[ls[tpl[i]]];
    for(RG int i = 1; i <= cntr; i ++)Sum += sum[ls[tpr[i]]];
    if(k <= Sum){
        for(RG int i = 1; i <= cntl; i ++)tpl[i] = ls[tpl[i]];
        for(RG int i = 1; i <= cntr; i ++)tpr[i] = ls[tpr[i]];
        return Query(l,mid,k);
    }
    else{
        for(RG int i = 1; i <= cntl; i ++)tpl[i] = rs[tpl[i]];
        for(RG int i = 1; i <= cntr; i ++)tpr[i] = rs[tpr[i]];
        return Query(mid+1,r,k-Sum);
    }
}

IL int Get(RG int l,RG int r,RG int k){
    cntl = cntr = 0;
    for(RG int i = (l-1); i ; i -= (i&-i))
        tpl[++cntl] = rt[i];
    for(RG int i = r; i ; i -= (i&-i))
        tpr[++cntr] = rt[i];
    return Query(1,lg,k);
}

int main(){
    freopen("testdate.in","r",stdin);
    cin>>N>>M;
    for(RG int i = 1; i <= N; i ++)
        cin>>a[i]  , oder[++lg] = a[i];
    char od; int l,r,k;
    for(RG int i = 1,c; i <= M; i ++){
        cin>>od;
        if(od == 'Q')cin>>l>>r>>k,qs[i] = (Ques){l,r,k};
        else cin>>l>>k,qs[i] = (Ques){l,0,k},oder[++lg] = k;
    }
    sort(oder+1,oder+lg+1);
    lg = unique(oder+1,oder+lg+1) - oder - 1;
    for(RG int i = 1; i <= N; i ++)Modify(i,1);
    for(RG int i = 1; i <= M; i ++)
    {
        if(!qs[i].r){
            Modify(qs[i].l , -1);
            a[qs[i].l] = qs[i].k;
            Modify(qs[i].l , 1);
        }
        else printf("%d\n",oder[Get(qs[i].l,qs[i].r,qs[i].k)]);
    }
    return 0;
}

Luogu Dynamic Ranking (带修改的主席树)的更多相关文章

  1. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  2. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  3. 【带修改的主席树】BZOJ1901-Dynamic Rankings

    稍后整理笔记.这题数据范围好像有点问题? #include<iostream> #include<cstdio> #include<cstring> #includ ...

  4. POJ2104 K-th Number 不带修改的主席树 线段树

    http://poj.org/problem?id=2104 给定一个序列,求区间第k小 通过构建可持久化的点,得到线段树左儿子和右儿子的前缀和(前缀是这个序列从左到右意义上的),然后是一个二分的ge ...

  5. 【poj1901-求区间第k大值(带修改)】树状数组套主席树

    901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7025  Solved: 2925[Sub ...

  6. [Luogu 3701] 「伪模板」主席树

    [Luogu 3701] 「伪模板」主席树 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 ...

  7. BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树

    题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...

  8. Dynamic Rankings—带单点修改的主席树

    这道题应该是很不错的板子了\(\mathcal{\color{cyan}{Link}}\) \(\mathcal{\color{red}{Description}}\) 给定一个序列,有两种操作.一是 ...

  9. Dynamic Rankings ZOJ - 2112(主席树+树状数组)

    The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...

随机推荐

  1. Gentoo(贱兔)Linux安装笔记

      网上对于Gentoo Linux 的教程少之又少,所以这里我将自己的安装记录贴出来 希望对正在研究Gentoo 的小伙伴们有帮助! 1.确认连接到互联网,使用net-setup工具配置网络 roo ...

  2. laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)

    首先大家想一想什么是容器,字面意思就是盛放东西的东西,常见的变量,对象属性都是容器,一个容器能够装什么东西,完全在于你对这个容器的定义.有的容器不仅仅只是存文本,变量,而是对象,属性,那么我们通过这种 ...

  3. Atom Mac安装 有快捷方式

    https://jeffjade.com/2016/03/03/2016-03-02-how-to-use-atom/ 如何在 PyCharm 中使用 MacDown 作为外部编辑器 新编码神器Ato ...

  4. 并行执行 Job - 每天5分钟玩转 Docker 容器技术(134)

    有时,我们希望能同时运行多个 Pod,提高 Job 的执行效率.这个可以通过 parallelism 设置. 这里我们将并行的 Pod 数量设置为 2,实践一下: Job 一共启动了两个 Pod,而且 ...

  5. Android Native App自动化测试实战讲解(上)(基于python)

    1.Native App自动化测试及Appuim框架介绍 android平台提供了一个基于java语言的测试框架uiautomator,它一个测试的Java库,包含了创建UI测试的各种API和执行自动 ...

  6. mysql5.7中解决中文乱码的问题

    在使用mysql5.7时,会发现通过web端向数据库中写入中文后会出现乱码,但是在数据库中直接操作SQL语句插入数据后中文就显示正常,这个问题怎么解决呢?此处不对mysql的数据编码过程和原理进行讲解 ...

  7. RAC节点两边存储名字不一致导致的故障及相关延伸

    起因:一个客户的实际故障,该故障非常典型,其他客户类似的环境也非常多,所以很值得梳理并记录下来. 环境:Oracle 11.2.0.4 RAC(2 nodes)+ RHEL 6.6 共享存储:EMC ...

  8. Activiti 中的ACT_RU_TASK表中的EXECUTION_ID和PROC_INST_ID区别

    当你的流程图为单向的时候则EXECUTION_ID和PROC_INST_ID是一样的 这种的流程图的话是一样的 这种的话就到支流是不一样的由于在节点处进行了分支,导致这个有三个方案.导致里面的分支分离 ...

  9. mysql常用脚本及命令记录

    mysql导出用户权限 mysql中直接通过授权即可使用对应用户,不必使用创建用户命令(如CREATE USER 'xxx'@'%' IDENTIFIED BY 'XXX';)先建用户再授权. 方法一 ...

  10. Luogu P1757 通天之分组背包

    题目背景 直达通天路·小A历险记第二篇 题目描述 自01背包问世之后,小A对此深感兴趣.一天,小A去远游,却发现他的背包不同于01背包,他的物品大致可分为k组,每组中的物品相互冲突,现在,他想知道最大 ...