在线查询第K个元素

21 篇文章 0 订阅
20 篇文章 1 订阅

 

分块思想(参考算法笔记):

假设数组大小为N,那么我们把数组分成 block_num = sqrt(N)个块【向上取整】,每个块的范围是 block_size = sqrt(N)【向下取整】,用 block[i]记录第 i 块的元素个数 ,然后再开一个数组 table[i] 记录数值为 i 的元素个数 

添加元素 x 的时候,计算元素对应的块号为idx = x / block_size ,然后令 block[idx]+=1 , table[x] +=1

删除元素 x 的时候,计算元素对应的块号为idx = x / block_size,然后令 block[idx] -=1 , table[x] -=1

查询第 k 个元素的时候,

首先在块间搜索,遍历block数组,统计元素的个数,这里我们用sum统计个数,如果sum + block[idx] >= K,说明第 k 个元素在第 idx 块。

这个时候我们进入块内搜索,计算块的开始地址:begin = idx * block_size,end = begin + block_size ,我们取 遍历 table[ begin , end ) ,如果sum + table[i] >= K ,说明 i 就是第 k 个元素

 

#define maxn 100001
#define sqrN 316
int block[maxn], table[maxn];

void push(int x) {
	int idx = x / sqrN;
	block[idx]++;
	cnt[x]++;
}

bool pop(int x) {
	int idx = x / sqrN;
	if (block[idx] == 0)return false;
	block[idx]--;
	cnt[x]--;
	return true;
}

int getKth(int K) {
	int sum = 0;
	int idx = 0;
	while (sum + block[idx] < K) {
		sum += block[idx++];
	}
	int num = idx*sqrN;
	while (sum + table[num] < K) {
		sum += table[num++];
	}
	return num;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值