题目大意:维护带修改区间 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. Redis常用操作-------Key(键)

    1.DEL key [key ...] 删除给定的一个或多个 key . 不存在的 key 会被忽略. 可用版本: >= 1.0.0 时间复杂度: O(N), N 为被删除的 key 的数量. ...

  2. NOIP模拟赛20180917 隐藏题目

    给定n个数,值域范围1~n,每个数都不同,求满足所有相邻数不同的排列数.\(n\le 30\). 状压DP很好想,然而我考试时没写出来.对于排列还是有很多转化方法.另外要注意数据范围.

  3. 【2016.3.18】作业 VS2015安装&单元测试(2)

  4. js 时间戳转换为日期格式

     //将1525854409000类型的时间转换成“yyyy-MM-dd”或“yyyy-MM-dd hh:mm:ss”   //info.birthday是后台获取到的Date类型的出生日期数据, / ...

  5. 《Linux内核分析》第六周学习小结

    进程的描述和进程的创建 一.进程的描述 进程描述符task_struct数据结构: (1)操作系统的三大功能: 进程管理.内存管理.文件系统 (2)进程的作用: 将信号.进程间通信.内存管理和文件系统 ...

  6. 开源的CAS实现SSO

    https://www.ibm.com/developerworks/cn/opensource/os-cn-cas/index.html ISC是基于CAS定制的,使用的高级的代理模式. https ...

  7. ODAC 下载

    官网地址: https://www.oracle.com/technetwork/topics/dotnet/downloads/odacdev-4242174.html 官方说说明: ODAC 18 ...

  8. ionic2添加 android平台出现的问题

    nodejs版本不宜过高  cordova版本不宜过高 此情况应采取 cordova platform add android --nofetch

  9. 理解 Delphi 的类(十) - 深入方法[17] - 提前声明

    //要点17: 如果前面的方法要调用后面的方法, 后面的方法需要提前声明 function MyFunB(x: Integer): Integer; forward; {使用 forward 指示字提 ...

  10. Highcharts之3D柱状图

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...