题目大意:维护带修改区间 K 小值。

题解:学习到了树状数组套权值线段树。

主席树,即:可持久化权值线段树,支持维护静态区间的 K 小值问题,其核心思想是维护 N 棵权值线段树,每个线段树维护的是序列 [1,i] 的权值,并根据可持久化思想使得空间复杂度维持在 \(O(nlogn)\)。

树状数组套权值线段树,支持维护带修改区间 K 小值的问题,其核心思想是改变静态主席树中各个权值线段树的前缀和处理方式,在这里采用树状数组中的前缀和处理方式,平衡了修改和查询的时间和空间。时间和空间复杂度为 \(O(nlognlogn)\)。注意:这里 log 是以 2 为底的对数。1e5 的 log2 大约为16,因此内存开 300 倍。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10; inline int read(){
int x=0,f=1;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
return f*x;
} char opt[5];
int n,m,a[maxn],tmp[2][20],cnt[2];
int d[maxn<<1],len;
struct operation{bool tag;int l,r,k;int pos,val;}q[maxn];
struct node{
#define ls(x) t[x].lc
#define rs(x) t[x].rc
int lc,rc,sum;
}t[maxn*300];
int tot,root[maxn];
inline void pushup(int o){t[o].sum=t[ls(o)].sum+t[rs(o)].sum;}
void insert(int &o,int l,int r,int pos,int val){
if(!o)o=++tot;
if(l==r){t[o].sum+=val;return;}
int mid=l+r>>1;
if(pos<=mid)insert(ls(o),l,mid,pos,val);
else insert(rs(o),mid+1,r,pos,val);
pushup(o);
}
int query(int l,int r,int k){
if(l==r)return l;
int mid=l+r>>1;
int lsize=0;
for(int i=1;i<=cnt[1];i++)lsize+=t[ls(tmp[1][i])].sum;
for(int i=1;i<=cnt[0];i++)lsize-=t[ls(tmp[0][i])].sum;
if(k<=lsize){
for(int i=1;i<=cnt[1];i++)tmp[1][i]=ls(tmp[1][i]);
for(int i=1;i<=cnt[0];i++)tmp[0][i]=ls(tmp[0][i]);
return query(l,mid,k);
}else{
for(int i=1;i<=cnt[1];i++)tmp[1][i]=rs(tmp[1][i]);
for(int i=1;i<=cnt[0];i++)tmp[0][i]=rs(tmp[0][i]);
return query(mid+1,r,k-lsize);
}
}
inline int lowbit(int x){return x&-x;}
inline void add(int x,int val){
int pos=lower_bound(d+1,d+len+1,a[x])-d;
for(int i=x;i<=n;i+=lowbit(i))insert(root[i],1,len,pos,val);
}
int querykth(int l,int r,int k){
memset(tmp,0,sizeof(tmp)),cnt[1]=cnt[0]=0;
for(int i=r;i;i-=lowbit(i))tmp[1][++cnt[1]]=root[i];
for(int i=l-1;i;i-=lowbit(i))tmp[0][++cnt[0]]=root[i];
return query(1,len,k);
} void read_and_parse(){
n=read(),m=read();
for(int i=1;i<=n;i++)d[++len]=a[i]=read();
for(int i=1;i<=m;i++){
scanf("%s",opt);
if(opt[0]=='Q')q[i].tag=0,q[i].l=read(),q[i].r=read(),q[i].k=read();
else q[i].tag=1,q[i].pos=read(),d[++len]=q[i].val=read();
}
sort(d+1,d+len+1);
len=unique(d+1,d+len+1)-d-1;
for(int i=1;i<=n;i++)add(i,1);
} void solve(){
for(int i=1;i<=m;i++){
if(q[i].tag){
add(q[i].pos,-1);
a[q[i].pos]=q[i].val;
add(q[i].pos,1);
}else{
printf("%d\n",d[querykth(q[i].l,q[i].r,q[i].k)]);
}
}
} int main(){
read_and_parse();
solve();
return 0;
}

【洛谷P2617】Dynamic Rankings的更多相关文章

  1. 洛谷P2617 Dynamic Rankings (主席树)

    洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...

  2. 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)

    P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  3. 洛谷 P2617 Dynamic Rankings 解题报告

    P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...

  4. 洛谷 P2617 Dynamic Rankings || ZOJ - 2112

    写的让人看不懂,仅留作笔记 静态主席树,相当于前缀和套(可持久化方法构建的)值域线段树. 建树方法:记录前缀和的各位置的线段树的root.先建一个"第0棵线段树",是完整的(不需要 ...

  5. 洛谷P2617 Dynamic Rankings

    带修主席树模板题 主席树的单点修改就是把前缀和(大概)的形式改成用树状数组维护,每个树状数组的元素都套了一个主席树(相当于每个数组的元素root[i]都是主席树,且这个主席树维护了(i - lowbi ...

  6. 洛谷P2617 Dynamic Rankings 主席树 单点修改 区间查询第 K 大

    我们将线段树套在树状数组上,查询前预处理出所有要一起移动的节点编号,并在查询过程中一起将这些节点移到左右子树上. Code: #include<cstdio> #include<cs ...

  7. 洛谷$P2617\ Dynamic\ Rankings$ 整体二分

    正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...

  8. 洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)

    洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真 ...

  9. 洛谷 P2617 Dynamic Ranking

    题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤ ...

  10. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

随机推荐

  1. ABP module-zero +AdminLTE+Bootstrap Table+jQuery权限管理系统第十四节--后台工作者HangFire与ABP框架Abp.Hangfire及扩展

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 HangFire与Quartz.NET相比主要是HangFire的内置提供集成化的控制台,方便后台查看及监控,对于 ...

  2. jenkins中配置svn 出现absolute path is not allowed

    代码: 兵马未动,粮草先行 作者: 传说中的汽水枪 如有错误,请留言指正,欢迎一起探讨. 转载请注明出处. 想用jenkins作自动化部署tomcat. svn代码已经checkout到本地目录了(/ ...

  3. 继承:call、apply、bind方法

    javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. call,apply,bind这 ...

  4. D. Little C Loves 3 II

    传送门 [http://codeforces.com/contest/1047/problem/D] 题意 给你n*m得棋盘,让你找两点之间距离为3的点的个数,不能重复使用,距离定义,两坐标差绝对值之 ...

  5. 开源RabbitMQ操作组件

    开源RabbitMQ操作组件 对于目前大多的.NET项目,其实使用的技术栈都是差不多,估计现在很少用控件开发项目的了,毕竟一大堆问题.对.NET的项目,目前比较适合的架构ASP.NET MVC,ASP ...

  6. WIN10 评估版 查看过期时间

    命令行运行winver,弹出的窗口显示过期时间,如 下图: 又可以再用一段时间教育版了,本机预装的的家庭版序列号,还没法从教育版降级到家庭版,可悲吧(win7时代就不允许从高级降低到低级用啊)

  7. jq源码解析之绑在$,jQuery上面的方法

    1.当我们用$符号直接调用的方法.在jQuery内部是如何封装的呢?有没有好奇心? // jQuery.extend 的方法 是绑定在 $ 上面的. jQuery.extend( { //expand ...

  8. mysql复杂查询

    所谓复杂查询,指涉及多个表.具有嵌套等复杂结构的查询.这里简要介绍典型的几种复杂查询格式. 一.连接查询 连接是区别关系与非关系系统的最重要的标志.通过连接运算符可以实现多个表查询.连接查询主要包括内 ...

  9. java中的随机数Random

    java中一般有两种随机数,一个是Math中random()方法,一个是Random类. 一.Math.random()  :     随即生成0<x<1的小数 实例:如何写,生成随机生成 ...

  10. [日常工作] cmd以及bash 直接使用当前目录的方法

    1. 从知乎学到了一点.. 2. 之前想在比如f:\a\b 目录下执行cmd命令的时候 总是需要先 f: 再cd目录的方式. 3. 知乎上面学到 发现可以通过在当前目录下面 输入  cmd 或者是 b ...