题目大意:

网址: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. GitLab简单使用

    [权限] ①已经搭建了Gitlab服务器,并已开通  http://git.******.com 权限(每个公司的git地址不一致),登陆到git中去: ②已经开通了项目权限(有专人负责开通): 当开 ...

  2. iptables snat和dnat

    iptables中的snat和dnat是非常有用的,感觉他们二个比较特别,所以单独拿出来说一下. dnat是用来做目的网络地址转换的,就是重写包的目的IP地址.如果一个包被匹配了,那么和它属于同一个流 ...

  3. file_put_contents写入文字换行

    file_put_contents写入文字换行 注意要使用双引号 "\r\n"

  4. Window Server 布署 WCF 服务 , 权限配置问题

    起因: 客户服务器运行环境要求提高安全性,建议数据连接串采取 加密措施 ,或改用 Window 验证 连接数据库服务 .于是我们打算选择后着,将后台服务(Window Server)数据库连接串调整为 ...

  5. 01. SELECT显示和PRINT打印超长的字符

    从SQL Server 2005开始,引入了varchar(max) / nvarchar(max) 数据类型,表中可不使用LOB数据类型,从而突破单列8000 / 4000字符的限制,动态SQL也可 ...

  6. QPS/TPS简介

    系统吞度量要素 一个系统的吞度量(承压能力)与request对CPU的消耗.外部接口.IO等等紧密关联.单个reqeust 对CPU消耗越高,外部系统接口.IO影响速度越慢,系统吞吐能力越低,反之越高 ...

  7. PHP文件头BOM头问题

    前几天我们公司服务器出现了一个离奇的问题,服务器与本地文件代码完全一致,本地运行正常,到了测试环境服务器之后,各种问题一个又一个浮现,先是后台验证码不显示,以为是session写入失败,又是怀疑gd库 ...

  8. Nginx location配置详细解释

    nginx location配置详细解释 语法规则: location [=|~|~*|^~] /uri/ { - } = 开头表示精确匹配 ^~ 开头表示uri以某个常规字符串开头,理解为匹配 ur ...

  9. CodeForces - 796D Police Stations bfs

    思路:删除尽量多的边使得所有点都能在限制距离之内到达一个警局,删除边会形成多棵子树,最多只能k棵.其实就是以每个警局为根结点,把整棵树划分为以警局为根结点的k棵树,说明要删除的边的数量就是k-1条,即 ...

  10. iBrand 产品工具包:Laravel Database Logger

    iBrand 社交新零售电商产品从2016年9月启动至今,已经趋于稳定,而且已经初步得到市场的检验,特别能抗住电商中秒杀时高并发的交易场景. 接下来我们团队会逐步开源一些正在使用的工具和解决方案,并且 ...