实用技巧——数状数组

1.划分区间区间结尾是R,区间长度等于R的 二进制分解 下最小的2的次幂,即lowbit®7->[7,7],[6,5],[4,1](分的过程就是求出7->6->4->0)lowbit实现while(x>0){ cout<<x-(x&(-x))+1<<" "<<x<<endl; x-=x&(-x);}...
摘要由CSDN通过智能技术生成
  1. 划分区间

区间结尾是R,区间长度等于R的 二进制分解 下最小的2的次幂,即lowbit®
7->[7,7],[6,5],[4,1](分的过程就是求出7->6->4->0)

注意:lowbit与 <<和>>不能混用


实现:
x+=x&-x向上走
x-=x&-x向下走

2.理解
在这里插入图片描述
数状数组其实就是以 在二进制补码中 出现1 的位置为区分点 ,将数组分割,继而求区间上的问题(黑色的块就是切分点,白色的就是区间)
类似,线段树就是以mid为切分点
查询过程
在这里插入图片描述

3.用途:维护序列前缀和,也就是正常前缀和修改一个数要(n2)这样减少时间
给定序列a,建立数组c,c[x]保存序列a的区间[x-lowbit(x)+1,x]中所有数的和,可查询可增加数

3.区间加(没用)
序列a的前缀和a[1~x]整体增加值

for(int i=1;i<=x;i++){
   
	for(int j=1;j<=i;j++){
   
		a[i]+=b[j];
	}
}

改写为一层循环就是将

for(int j=1;j<=i;j++){
   
	a[i]+=b[j];
}

变为区间乘法
(x-i+1)*b[i]

int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
   
		cin>>c[i];
	}
	int s,e,v;
	scanf("%d%d%d",&s,&e,&v);
	b[s]=v;
	b[e+1]=-1*v;
	int x;
	scanf("%d",&x);
	int sum=0;
	for(int i=1
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值