POJ2104 区间第k大(带修改)

学习笔记: 进阶版树状数组(区间修改区间查询以及查询第K大元素) 导 树状数组相信大家都很熟悉了,而今天我将会为大家带了一些更加全面的操作,并且欢迎补充哦。 其实我想说的是,除了RMQ,线段树能做的,树状数组都能做。 换句话说,这是一个稍微进阶版的的树状数组,读者至少要会单调修改区间查询这个最基本的操作。 树状数组应该算是常数非常小的数据结构啦。而小生特别喜欢这个数据结构,这是因为它特别短,就是又短又快! 核心操作:lowbit int ... 阅读详情

Description

  给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
  1、查询A[i],A[i+1],A[i+2],…,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
  2、修改A[i]的值为j。
  所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。

Input

  输入文件的第一行包含两个整数N和M,分别表示序列的长度为N和有M个操作。
  接下来的N个不大于10^9正整数,第i个表示序列A[i]的初始值。
  然后的M行,每行为一个操作Q i j k 或者C i j分别表示查询A[i],A[i+1],A[i+2],…,A[j](1<=i<=j<=N)中,升序排列后排名第k的数和修改A[i]的值为j。

Output

  对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。

Sample Input

5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3

Sample Output

3 6

Hint

【数据范围】:
  20%的数据中,m,n≤100; 
  40%的数据中,m,n≤1000; 
  100%的数据中,m,n≤10000。

打一发树套树,表示splay的哪个旋转到根下面的写法好迷。。

树套树常数贼大= =主席树貌似好用不少(还没复习233)

#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
const int N = 1e4+10,Maxsiz = N*log2(N)*2;
int n,m,a[N];
struct Splay{
	int p[Maxsiz],ch[Maxsiz][2];
	int cnt,k[Maxsiz],siz[Maxsiz];
	#define Ls(v) ch[v][0]
	#define rs(v) ch[v][1]
	#define sum(v) siz[v]=siz[Ls(v)]+siz[rs(v)]+1
	inline void rotate(int x){
		int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[x][!tp];
		ch[p[son]=f][tp]=son,sum(f);
		ch[p[f]=x][!tp]=f,sum(x);
		ch[p[x]=gf][rs(gf)==f]=x;
	}
	inline void splay(int x,int &rt){
		while(p[x]){
			if((p[p[x]])&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
			rotate(x);
		}
		rt=x;
	}
	inline void newnode(int x,int v,int Fa){
		siz[x]=1;
		p[x]=Fa;
		k[x]=v;
	}
	inline void insert(int &x,int v,int Fa,int &root){
		if(!x)return newnode(x=++cnt,v,Fa),splay(x,root),void();
		insert(ch[x][k[x]<v],v,x,root);
	}
	inline int Query(int x,int v){
		int tot=0;
		while(x)k[x]<=v?tot+=siz[Ls(x)]+1,x=rs(x):x=Ls(x);
		return tot;
	}
	inline int findpre(int x){
		for(x=Ls(x);rs(x);x=rs(x));
		return x;
	}
	inline int findsub(int x){
		for(x=rs(x);Ls(x);x=Ls(x));
		return x;
	}
	inline void delet(int x,int v,int &root){
		for(;k[x]^v;x=ch[x][k[x]<v]);
		splay(x,root);
		if(!Ls(x))return p[root=rs(x)]=0,void();
		int pre=findpre(x);
		splay(pre,root);
		rs(pre)=rs(x);
		if(rs(x))p[rs(x)]=pre;
		sum(pre);
	}
}sp;
struct SegMent{
	struct tree{
		int L,r,rt;
	}t[N<<2];
	#define Lc v<<1
	#define rc v<<1|1
	inline void Modify(int v,int x,bool cmd){
		if(t[v].L>x||t[v].r<x)return ;
		cmd?sp.insert(t[v].rt,a[x],0,t[v].rt):sp.delet(t[v].rt,a[x],t[v].rt);
		if(t[v].L==t[v].r)return ;
		Modify(Lc,x,cmd),Modify(rc,x,cmd);
	}
	inline int Query(int v,int A,int b,int k){
		if(t[v].L>b||t[v].r<A)return 0;
		if(A<=t[v].L&&t[v].r<=b)return sp.Query(t[v].rt,k);
		return Query(Lc,A,b,k)+Query(rc,A,b,k);
	}
	inline void build(int v,int L,int r){
		t[v]=(tree){L,r};
		Inc(i,L,r)sp.insert(t[v].rt,a[i],0,t[v].rt);
		if(L==r)return ;
		int Mid=L+r>>1;
		build(Lc,L,Mid),build(rc,Mid+1,r);
	}
}tr;
inline void init(){
	scanf("%d%d",&n,&m);
	Inc(i,1,n)scanf("%d",&a[i]);
	tr.build(1,1,n);
}
inline void Modify(){
	int x,k;scanf("%d%d",&x,&k);
	tr.Modify(1,x,0);
	a[x]=k;
	tr.Modify(1,x,1);
}
inline void Query(){
	int ans,L,r,kth;
	scanf("%d%d%d",&L,&r,&kth);
	for(int x=tr.t[1].rt;x;){
		int tmp=tr.Query(1,L,r,sp.k[x]);
		if(tmp<kth)x=sp.rs(x);
		else ans=sp.k[x],x=sp.Ls(x);
	}
	cout<<ans<<"\n";
}
inline void solv(){
	Inc(i,1,m){
		char c=getchar();while((c^'Q')&&(c^'C'))c=getchar();
		c=='Q'?Query():Modify();
	}
}
int main(){
	init();
	solv();
	return 0;
}

补一个主席树,,

和静态版本略有不同(我感觉完全不一样。。),说的可能有点乱,大概是那个意思。

查询区间[l,r],由于主席树的前缀和性质想到树状数组,常规的树状数组直接改点值,我们不过是把点值换成了整棵线段树。

简单地说,就是树状数组套上多棵动态开点的权值线段树。

但是这样写就不满足主席树只加点不删除的性质。。我也很迷~主席树的定义到底是个什么= =

再补:满足前缀和性质的线段树就是主席树~

#include<bits/stdc++.h>
using namespace std;
const int Maxn=10005;
int n,a[Maxn];
struct SegMent{
	struct tree{
		int ls,rs,siz;
	}t[Maxn*40];int cnt;
	inline void modify(int &x,int v,int l,int r,int cmd){
		if(l>v||r<v)return ;
		t[x?:x=++cnt].siz+=cmd;
		if(l==r)return ;
		int mid=l+r>>1;
		modify(t[x].ls,v,l,mid,cmd),modify(t[x].rs,v,mid+1,r,cmd);
	}
}seg;
struct BIT{
	int root[Maxn];
	int q[2][Maxn];
	#define lowbit(x) (x)&-(x)
	inline void update(int x,int k,int cmd){
		for(;x<=n;x+=lowbit(x))seg.modify(root[x],k,0,(1<<30),cmd);
	}
	inline void getroot(int l,int r){
		for(q[0][0]=0;l>0;l-=lowbit(l))q[0][++q[0][0]]=root[l];
		for(q[1][0]=0;r>0;r-=lowbit(r))q[1][++q[1][0]]=root[r];		
	}
	inline int sum(bool t){
		int ret=0;
		for(int i=1;i<=q[t][0];++i)ret+=seg.t[seg.t[q[t][i]].ls].siz;
		return ret;
	}
	inline int query(int l,int r,int k){
		if(l==r)return l;
		int size=sum(1)-sum(0);
		int mid=l+r>>1;
		if(size>=k){
			for(int i=1;i<=q[0][0];++i)q[0][i]=seg.t[q[0][i]].ls;
			for(int i=1;i<=q[1][0];++i)q[1][i]=seg.t[q[1][i]].ls;
			return query(l,mid,k);
		}else {
			for(int i=1;i<=q[0][0];++i)q[0][i]=seg.t[q[0][i]].rs;
			for(int i=1;i<=q[1][0];++i)q[1][i]=seg.t[q[1][i]].rs;
			return query(mid+1,r,k-size);
		}
	}
}bit;
int main(){
	int m;scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	for(int i=1;i<=n;++i)bit.update(i,a[i],1);
	for(int i=1;i<=m;++i){
		char c=getchar();while(!isalpha(c))c=getchar();
		if(c=='C'){
			int x,k;scanf("%d%d",&x,&k);
			bit.update(x,a[x],-1);
			bit.update(x,a[x]=k,1);
		}else {
			int l,r,k;scanf("%d%d%d",&l,&r,&k);
			bit.getroot(l-1,r);
			printf("%d\n",bit.query(0,(1<<30),k));
		}
	}
	return 0;
}

 

区间第K值带修改 分块 区间第K值带修改 Q:给定一个序列 1、查询一个L到R的区间内的第K大(小)值。2、修改一个值。 这道神题困扰了我很久,直到学了各种各样的算法才会会这道题。 先比较一下流行的算法的效率吧 对于一个长度为N的序列 暴力:对于一段查询区间每次进行快排。 时间复杂度: 单次查询:O(NlogN) 修改:O(1) 空间复杂度:O(N) 线段树套平衡树: 单次查询:O(log^3 N) 阅读详情

相关推荐

区间修改、区间查询

区间修改、区间查询

11 323

区间元素可变(添加与删除)的第求k大数和给定数的排名问题

思想来源于张昆玮的《统计的力量》 划分树只能在静态区间上求第k大数和给定数的排名 基于字母数的动态性和数值大小的字典有序性,只要在其结点上存以当前节点结尾的串(数的二进制形式)的数目,和以该串为前缀的串的数目,便可在位模式长度时间内进行元素增添、删除和以上问题的求解。但当元素数值过大,可能出现时间常数过大的问题,并且空间需求不易估计。

qwe20060514的专栏 778

SAP BSP网页开发入门:从SE80创建到MVC实战(附成品展示)

本文详细介绍了SAP BSP网页开发的入门与实战,从SE80环境搭建到MVC架构实现的全流程。通过具体案例和代码示例,帮助开发者掌握业务服务器页面(BSP)技术,提升SAP Web化转型中的开发效率,适用于需要扩展SAP功能的企业场景。

x1y2z的博客 1万+

区间第k大的几种解法

区间第K大问题,变化包括带修改和不带修改,强制在线和允许离线 修改主要是单点修改,我们前面也只讨论这种情况。 接下来我们从编程复杂度和时空复杂度来讨论几种做法。 1.整体二分(编程复杂度:低-中,时间复杂度:优秀,空间复杂度:优秀) 缺点:只能做离线 优点:空间都是O(n)。常数小。带修改O(nlog2n),不带修改O(nlogn)。 但是不带修改的情况,如果允许的话,...

weixin_30564785的博客 728

疑难问题(二)——PyTorch 2.3.0 ‘import torch‘ 错误排查:深入解析‘shm.dll‘加载失败与系统路径修复

本文深入解析了在Windows系统上安装PyTorch 2.3.0后,执行'import torch'时遇到的'shm.dll'加载失败错误(OSError)。该问题通常源于系统DLL搜索路径缺失,导致无法找到关键的共享内存通信组件或其依赖项。文章提供了核心解决方案:通过手动修改PyTorch的`__init__.py`文件,将用户基目录下的Library\bin路径添加到DLL搜索列表中,从而从根本上修复此导入错误,并给出了详细的修改步骤和验证方法。

weixin_29056865的博客 305

CHNS数据库下载与使用指南:从申请到导入的全流程解析

面板数据是经济学与公共卫生实证研究的重要支撑。中国健康与营养调查(CHNS)自1989年持续追踪中国居民的家庭与个人健康、营养及经济行为,为研究者提供了跨度近三十年的纵向微观数据。理解CHNS的数据组织原理与申请机制,是高效利用该数据的前提。该数据广泛适用于健康经济学、膳食营养分析及公共政策评估等场景。围绕CHNS的下载流程,完整梳理了注册申请、数据文件解析以及Stata、R、Python三种工具的读取方法,并针对邮箱验证、文件损坏、ID匹配等常见问题提供排查建议,帮助研究者快速建立数据处理基础。

weixin_33624741的博客 283

【poj2104】不带修改的区间第k大 主席树

【题目大意】 给定一个长为N的序列,每个序列的权值为Ai.有M个询问,每个询问为(L,R,K),分别代表[L,R]的第K大的数。 期中n=100000,m=5000 【题解】 用主席树解决,那么什么是主席树呢? 首先我们先明确一下权值线段树的概念。 平常我们用的线段树都是区间线段树,而权值线段树和平衡树中树的结点意义是类似的。 权值线段树中(下文所说线段树均值权值线段树),每个结

chty_syq的博客 375

地下管网巡检机器人:基于YOLOv8与UI界面的智能化系统设计与实现

通过YOLOv8模型的目标检测功能结合实时视频流,我们能够实现对地下管网巡检机器人的智能化控制。系统通过图像识别技术帮助巡检人员快速识别管道中的各种缺陷和障碍物,从而提高巡检效率和准确性。未来,我们可以继续优化模型,增加更多的目标类别,并通过强化学习等方法提高机器人的自主巡检能力。此外,随着硬件技术的发展,未来的巡检机器人可能会具备更强的感知能力和更高的智能水平。

YOLO 529

[POJ 2104]K-th Number (不带修改的区间k大,函数式线段树)

/* http://hi.baidu.com/wyl8899/item/e00796a9cb2df73d020a4d68 */ #include #include #include using namespace std; const int MAX_N=100005; const int MAX_M=5005; const int MAX=MAX_M*600; int n,m; int

Yukar_syt的专栏 910

人形机器人硬件电路设计入门

人形机器人属于。

blotemj.blog.youkuaiyun.com 229

贝叶斯机器学习在吸附量预测中的应用

本文介绍了贝叶斯机器学习在吸附量预测中的应用。通过Python实现完整的贝叶斯建模流程,包括数据生成、预处理、模型构建与评估。文章对比了贝叶斯与频率学派的差异,详细阐述了贝叶斯线性回归和神经网络的实现方法,并提供了数据可视化、模型诊断等技术细节。该方法不仅能预测吸附量,还能量化预测不确定性,为工程决策提供更全面的依据。全文超过6000字,结合理论推导与代码实践,是应用贝叶斯方法解决实际工程问题的完整指南。

AI的内部世界的博客 166

POJ-2104 K-th Number (主席树 不带修改区间第k大)

主席树 入门题。题意:1e5个数,5e4次询问,每次询问区间第k大。

hmc0411的博客 534

【安全启动】HSM安全启动原理与技术实现白皮书

摘要: 安全启动(Secure Boot)与度量启动(Measured Boot)通过硬件信任根(HSM/TPM等)确保系统启动链路的可信性,实现代码验证与状态记录。HSM作为核心组件,承担密钥保护、签名验证和密码运算任务,与SHE、TPM等协同构建分层信任链。通用计算与嵌入式/汽车场景的启动流程差异显著,前者依赖TPM的PCR度量,后者以HSM为核心实现硬件级安全闭环。工程实践中需权衡性能、合规性及抗攻击能力,并结合后量子密码(PQC)等演进技术优化方案。

weixin_46481662的博客 830

区间第k大(poj 2104)

#include #include #include #include #define maxn 1000005 using namespace std; vector dat[maxn*2]; int num[maxn],A[maxn]; int build (int o,int L,int R){ if (L==R){ dat[o].push_back(num[L]);

LHYL 849

【数据集实例】CMIP6气候模式数据下载-以河东地区为例

以河东地区为例,介绍CMIP6数据下载及处理

WW、forever的博客 4936

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【poj2104】区间第k大(版本1)

【POJ2104】区间第k大 Description 给定一个长度为n的序列,m个询问,每个询问的形式为:L,r,k表示在[L,r]间中的第k大元素。 Input 第1行:2个数,n,m表示序列的长度和询问的个数 第2行:n个数,表示n个数的大小 第3-m+2行:每行3个数,L,r,k表示询问在[L,r]区间内第k小的元素

袋鼠与蒟蒻 440

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

区间第K大(POJ-2104)

可持久化线段树不是一颗完全二叉树,所以不能用层次序编号,而应该直接记录每个节点的左、右子节点的编号。可持久化线段树维护了每次操作后线段树的历史形态。 下面举个简单的例子来理解一下: 以poj-2104为例;这棵树是一颗不用修改的线段树 题意:即多次查询,查询区间第K大的数。 POJ-2104 (区间第k大) //主席树的学习--区间第k大 //区间第k大又可以用整体分治算法,归并树,线段树套平衡树...

小` pi孩 283

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

主席树-区间第k大值(不带修改)

题目:poj2104 && hdu2665 题意:求区间第K大的值。 分析:资料1  主席树包含n棵线段树,这n棵线段树的形状完全相同。而且树与树之间有很大的重叠。 线段树root[i]表示数组a中区间[1,i]的元素插进线段树时的版本。 那么再添加一个元素a[i+1]时,只需修改线段树上的从根节点开始向下走的一条路径。 那么对于线段树root[i+1],我们先“拷贝”线段树root[

w20810的专栏 2142

POJ 2104 K-th Number【整体二分 + 树状数组】

本来只是想学一下CDQ,还是先把整体二分搞懂一点。这题窝几个月前分别用划分树,树套树,主席树和挑战上介绍的分桶法实现了一发(然而现在都忘得差不多了) 最快的是划分树,其次是主席树,然后是树套树,还有一个10000+ms分桶法的思想实现的,最上面的就是整体二分的方法。题目链接:http://poj.org/problem?id=2104题意:给定序列,求每次询问区间的第K大数。分析:首先介绍整体

Tuesday 8105

poj 2104 可持久化线段树 区间K大 不修改

poj 2104 区间k大 不修改 只查询 模板 #include #include #include #include #include #include #include #define N 240008 #define M 5500000 using namespace std; int n,m,rt[N]; struct Node{ int l,r,cnt;; }t

我的博客 296

poj 2104 区间第k大 主席树

/* 静态主席树求区间第K大 poj 2104 主要思想: 1. 将数据离散化 2. 用线段树来维护信息,维护处于该区间的数的个数 3. 将原有数组中的每一个数依次插入,每次插入一个值的时候新建一棵线段树 这样就有了n+1棵线段树,对于询问(l,r,k),只需查询T[l-1]和T[r]两棵线段树

legedexinshi的专栏 573

POJ 2104 可持久化线段树 求区间第k大

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 35455   Accepted: 11296 Case Time Limit: 2000MS Description You are working for Macrohard com

_rabbit的专栏 1408

【划分树】求区间K大数

<br />       求区间K大数,众所周知有二分答案+树套树的做法,每个询问复杂度为O(log3N),可谓近似一个O(N)了,不仅时间复杂度高,编程复杂度也不低,后来才发现还有一种叫划分树的数据结构,专门做这种问题。<br />      本来觉得知道个树套树就够了,据我所知划分树还不支持区间修改操作,但是这次NOI一试的piano偏偏那出题人就有这么重口味,给你来两个500000的点!真是不简单,当时我都在想有没有O(N)的算法了。树套树的复杂度偏偏就被卡掉了,三个点平均每个点要跑5秒,好吧,那就学

Evil.livE 4382

整体二分初探 两类区间第K大问题 poj2104 & hdu5412

看到好多讲解都把整体二分和$CDQ$分治放到一起讲 不过自己目前还没学会$CDQ$分治 就单独谈谈整体二分好了 先推荐一下$XHR$的 <浅谈数据结构题的几个非经典解法> 整体二分在当中有较为详细的讲解 先来说一下静态第$K$小的整体二分解法 $(POJ2104)$ 题目链接:http://poj.org/problem?id=2104 所谓整体二分 就是利用所有的询问相...

weixin_30621919的博客 141

POJ2104 K-th Number —— 区间第k小 整体二分

题目链接:https://vjudge.net/problem/POJ-2104 K-th Number Time Limit:20000MS Memory Limit:65536K Total Submissions:64110 Accepted:22556 Case Time Limit:2000MS ...

alince20008的博客 111

整体二分求区间第k大模板(POJ 2104)

自己的模板,线段树实现的,可以参考一下 算法步骤 参考一下文章 http://www.cnblogs.com/dirge/articles/5810855.html https://www.cnblogs.com/rayrayrainrain/articles/6477611.html //#include<bits/stdc++.h> #include&l...

Bowen的博客 551
上一篇: USACO 2009 January Gold 安全路径
下一篇: BZOJ3196 二逼平衡树
DancingZ
博客等级 码龄9年 10粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值