1901: Zju2112 Dynamic Rankings

本文介绍了一种结合树状数组与主席树的数据结构实现,主要用于解决支持修改操作的区间第K大问题。通过示例代码展示了如何进行区间查询及元素更新,并优化了处理效率。

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

树状数组套主席树,用于解决支持修改的区间k大问题。

由于主席树是一种前缀和,可以用树状数组将修改从n^2*loginf优化到n*logn*loginf。

板子题没有太多解释,直接挂代码。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define db double
#define ldb long double
#define pli pair<ll,int>
#define mkp make_pair
#define X first
#define Y second
const int N=50005,inf=1000000000;
struct TREE{int lc,rc,sum;}T[2000000];
int n,a[N],rt[N],numl[N],lnl,numr[N],lnr,tot;
void add(int x,int y,int l,int r,int &num){
	if(!num)num=++tot;
	T[num].sum+=y;
	if(l==r)return;
	int mid=l+r>>1;
	if(x>mid)add(x,y,mid+1,r,T[num].rc);
	else add(x,y,l,mid,T[num].lc);
}
int kth(int k,int l,int r){
	if(l==r)return l;
	int i,S=0;
	rep(i,1,lnr)S+=T[T[numr[i]].lc].sum;
	rep(i,1,lnl)S-=T[T[numl[i]].lc].sum;
	if(k>S){
		rep(i,1,lnr)numr[i]=T[numr[i]].rc;
		rep(i,1,lnl)numl[i]=T[numl[i]].rc;
		return kth(k-S,l+r+2>>1,r);
	}
	rep(i,1,lnr)numr[i]=T[numr[i]].lc;
	rep(i,1,lnl)numl[i]=T[numl[i]].lc;
	return kth(k,l,l+r>>1);
}
int main(){
	int Q,i,z,x,y,k;char str[2];
	scanf("%d%d",&n,&Q);
	rep(i,1,n){
		scanf("%d",&a[i]);
		for(z=i;z<=n;z+=z&-z)
			add(a[i],1,0,inf,rt[z]);
	}
	while(Q--){
		scanf("%s%d%d",str,&x,&y);
		if(str[0]=='C'){
			for(z=x;z<=n;z+=z&-z){
				add(a[x],-1,0,inf,rt[z]);
				add(y,1,0,inf,rt[z]);
			}
			a[x]=y;
		}
		else{
			scanf("%d",&k);
			for(lnl=0,z=x-1;z;z-=z&-z)numl[++lnl]=rt[z];
			for(lnr=0,z=y;z;z-=z&-z)numr[++lnr]=rt[z];
			printf("%d\n",kth(k,0,inf));
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值