前缀中位数 [树状数组]

本文介绍了一种使用树状数组(Binary Indexed Tree)来高效维护动态序列中位数的算法实现。通过读取输入数据,对数据进行排序和唯一化处理,再利用树状数组进行插入操作并查找中位数,最终输出每个步骤的中位数值。此方法适用于需要频繁更新数据集并快速获取中位数的场景。

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

传送门 

树状数组维护中位数 

#include<bits/stdc++.h>
#define N 200050
#define R register
using namespace std;
int n,a[N],b[N],c[N];
int read(){
	int cnt=0; char ch=0;
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
	return cnt; 
}
inline void Insert(int x,int val){for(;x<=n;x+=x&-x) c[x] += val;}
inline int find(int k){
	int ans=0,cnt=0;
	for(R int i=18;i>=0;i--) if(ans+(1<<i)<=n){
		ans += (1<<i); if(c[ans]+cnt>=k) ans -= (1<<i);
		else cnt += c[ans]; 
	}  return ans+1;
}
int main(){
	n=read();
	for(R int i=1;i<=n;i++) a[i] = b[i] = read();
	sort(b+1,b+n+1); int siz = unique(b+1,b+n+1) - (b+1);
	for(R int i=1;i<=n;i++) a[i] = lower_bound(b+1,b+siz+1,a[i]) - b;
	for(R int i=1;i<=n;i++){
		Insert(a[i],1); printf("%d\n",b[find((i+1)/2)]);
	} return 0;
}

 

### 树状数组前缀和的概念及联系 #### 一、树状数组的基础概念 树状数组(Binary Indexed Tree 或 Fenwick Tree)是一种用于高效计算动态数组前缀和的数据结构。其核心思想是通过一种特殊的数组存储方式来支持快速的单点更新以及范围查询操作[^2]。 树状数组的核心在于 `lowbit` 函数的应用,该函数可以提取一个整数最低位上的1及其后续0组成的数值。例如对于数字8 (二进制表示为1000),`lowbit(8)` 返回的是8本身;而对于9 (二进制表示为1001),返回的结果则是1。这种特性使得我们可以构建一棵隐式的树形结构,从而实现高效的前缀和查询功能[^1]。 #### 二、前缀和的基本定义 前缀和是指给定一个数组A,它的第i项前缀和S[i]等于从首元素到当前索引位置所有元素之和即 \( S[i]=\sum_{j=0}^{i}{A[j]} \)[^3]。如果仅需一次性获取整个数组的前缀和,则可以通过简单的线性扫描完成这一任务。然而当面对频繁修改或者多次询问不同区间的累积值时,朴素的方法效率低下,此时引入更高级别的工具如树状数组就显得尤为重要了。 #### 三、树状数组的操作方法 ##### 单点更新 假设我们需要改变原数组中的某个特定值a[x], 那么相应地也需要调整BIT(bit[]代表树状数组) 中涉及的所有节点: \[ bit[k]+=delta,\quad k+=k&(-k)\] 这里\( delta=a'[x]-a[x]\), 表示新旧两个版本之间差异部分; 同样采用循环直到超出边界为止. ##### 区间查询 为了得到任意指定下标的累计总和s[y]: \[ s[y]=\text{getSum}(y)=\sum_{i=1}^{y}\text{bit}[i].\] 具体做法是从目标坐标出发逐步回溯父结点直至起点处累加沿途经过的各项贡献值得到最后结果. \[ res += bit[y]; y -= lowbit(y);\] 以上两步构成了基本框架, 可以满足大多数场景需求.[^4] #### 四、区别与联系 尽管两者都服务于相同目的——加速针对连续片段内的汇总运算过程,但它们各自适用场合有所侧重: - **简单静态环境**: 如果只是单纯读取固定不变的一组数据并反复调用其中某些片断的信息的话,那么预处理好全局性的prefix_sum即可胜任工作。 - **动态变化条件下**: 当面临不断发生更改的情况比如增加删除替换等动作影响原始资料分布形态之时,则应该优先考虑运用更为灵活强大的tree-based solution也就是本文介绍过的binary indexed tree形式来进行管理控制。因为后者不仅能够很好地兼顾速度表现还能适应更加复杂的业务逻辑要求。 ```python def lowbit(x): return x & (-x) class BITree: def __init__(self, size): self.size = size self.tree = [0]*(size+1) def update(self,index,delta): while index<=self.size: self.tree[index] += delta index += lowbit(index) def getPrefixSum(self,index): result = 0 while index>0: result += self.tree[index] index -= lowbit(index) return result ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值