题目大意:

网址: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. Composer 结合 Git 创建 “服务类库”

    Composer 结合 Git 创建 "服务类库" 我一直认为,现在的 PHP 已经进展到了工程化的领域.以前的 PHP 开发者,以快为美,速度和规模永远都是矛盾体.现在的 PHP ...

  2. PLECS—直流电机系统2

    1.模型图 2,计算及仿真 1)计算   2)仿真 n = 1870.1 r/min (wm = 195.833 rad/s)                                     ...

  3. 导入sass文件

    4导入sass文件 sass的@import规则在生成css文件时就把相关文件导入进来.这意味着所有相关的样式被归纳到了同一个css文件中,而无需发起额外的下载请求. 1 sass局部文件的文件名以下 ...

  4. 基于agenda的Nodejs定时任务管理框架搭建

    0.背景 在大型项目中,定时任务的应用场景越来越广.一般来说,按照微服务的思想,我们会将定时任务单独部署一套服务,核心的业务接口独立到另一个服务中,从而降低相互之间的耦合程度.在需要使用定时任务时,只 ...

  5. Oracle中的多表查询(笛卡尔积原理)

    本次预计讲解的知识点 1. 多表查询的操作.限制.笛卡尔积的问题: 2. 统计函数及分组统计的操作: 3. 子查询的操作,并且结合限定查询.数据排序.多表查询.统计查询一起完成各个复杂查询的操作: 一 ...

  6. hibernate学习(六) flush()和clean()区别和使用

    session.flush()是强制和数据库同步 session.clean()是清除session中的缓存 对于批量数据插入的时候优化:减少cpu和内存(缓存)占用量 @Test public vo ...

  7. iOS开发引入第三方类库的问题

    在开发iOS程序的过程中,通常在导入第三方的类库(.a/.o)文件会报出一系列的错误: Undefined symbols for architecture i386: "std::stri ...

  8. 腾讯云+校园扶持计划是bug还是福利

    前言   上午突然收到好友的微信消息.打开一看是关于关腾讯云"云+校园扶持计划".仔细看下了意思就是用户可以花360大洋购买腾讯云服务器配置为1核2G,1M带宽的服务器3年.(腾讯 ...

  9. iOS.Animations.by.Tutorials.v2.0汉化(四)

    第三章 转换 在前面的两章,你学习了如何创建基于视图位置和透明度alpha的动画属性的动画.但是,如果您希望在视图上添加动画或删除动画,您将如何处理呢? 您可以使用前几章的方法来设置进出界面的动画效果 ...

  10. linux RHCS集群 高可用web服务器

    RHCS集群,高可用服务器 高可用 红帽集群套件,提供高可用性,高可靠性,负载均衡,快速的从一个节点切换到另一个节点(最多16个节点)负载均衡 通过lvs提供负载均衡,lvs将负载通过负载分配策略,将 ...