#分块,二分#zoj 2112 Dynamic Rankings

本文介绍了一种解决区间动态第k小问题的有效算法。利用分块思想进行大段维护和小段朴素处理,通过二分查找确定目标值。文章包含完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

支持修改的区间动态第k小


分析

树状数组套主席树(主席树不支持单点修改)太麻烦了,所以就用一种虽然时间略长但是比较简短的代码,当然运用到大段维护,小段朴素的方法,具体就是二分答案,其实理解上去还是比较简单的


代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#define rr register
#define L(x) ((x-1)*bk+1)
#define R(x) (x*bk>n?n:x*bk)
#define max(a,b) ((a>b)?a:b)
int n,a[50001],b[50001],pos[50001];
inline int in(){//逐字符输入
	rr int ans=0; rr char c=getchar();
	while (c<48||c>57) c=getchar();
	while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
	return ans;
}
inline void resort(int x,int bk){//分块的思想(大段维护),所以要排序
	rr int l=L(x),r=R(x);
	for (rr int i=l;i<=r;++i) b[i]=a[i];
	std::sort(b+l,b+1+r);
}
inline void print(int ans){//逐字符输出
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline int answ(int l,int r,int v,int bk){
	rr int ans=0;
	if (pos[l]==pos[r]){//小段朴素
		for (rr int i=l;i<=r;++i) ans+=a[i]<=v;
	}
	else{
		for (rr int i=l;i<=R(pos[l]);++i) ans+=a[i]<=v;
		for (rr int i=pos[l]+1;i<pos[r];++i) ans+=std::upper_bound(b+L(i),b+1+R(i),v)-b-L(i);//大段维护
		for (rr int i=L(pos[r]);i<=r;++i) ans+=a[i]<=v;
	}
	return ans;
}
int main(){
	rr int t=in();
	while (t--){
		n=in(); rr int m=in(); rr int block=sqrt(n);
		rr int k=n/block,mx=0; if (n%block) k++;
		for (rr int i=1;i<=n;++i) a[i]=in(),mx=max(a[i],mx);//剪枝(不必要的就不要)
		for (rr int i=1;i<=n;++i) pos[i]=(i-1)/block+1;
		for (rr int i=1;i<=k;++i) resort(i,block);//初始分块
		while (m--){
			rr char c=getchar(); while (c!='Q'&&c!='C') c=getchar();  rr int x=in();
			if (c=='C') a[x]=in(),mx=max(a[x],mx),resort(pos[x],block);//修改
			else{
				rr int y=in(),k=in(); rr int l=1,r=mx;//二分答案
				while (l<r){
					rr int mid=(l+r)>>1;
					if (answ(x,y,mid,block)>=k) r=mid; else l=mid+1;
				}
				print(l); putchar('\n');
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值