当前位置: 首页 > news >正文

YBTOJ 树状数组 二进制

qwq

这道题自己没想出来,是看全网首A的神仙的博客学会的,写这篇文章主要是思路梳理吧。

考虑 x x x a n d and and 2 k 2^k 2k 在二进制第 k + 1 k+1 k+1 位的值:当 x ∈ [ 0 , 2 k − 1 ] x\in[0,2^k-1] x[0,2k1] 时为 0 0 0 x ∈ [ 2 k , 2 k + 1 − 1 ] x\in[2^k,2^{k+1}-1] x[2k,2k+11] 时为 1 1 1 x ∈ [ 2 k + 1 , 2 k + 1 + 2 k − 1 ] x\in[2^{k+1},2^{k+1}+2^k-1] x[2k+1,2k+1+2k1] 时又为 0 0 0……以此类推,得出一般性结论:当且仅当 x m o d    2 k + 1 ∈ [ 2 k , 2 k + 1 − 1 ] x\mod 2^{k+1}\in[2^k,2^{k+1}-1] xmod2k+1[2k,2k+11] x x x a n d and and 2 k 2^k 2k 在二进制第 k + 1 k+1 k+1 位的值为 1 1 1

那么想要求 ( a [ i ] + x ) (a[i]+x) (a[i]+x) a n d and and y y y 的值,就可以对 y y y 进行二进制拆分, y y y 的第 k + 1 k+1 k+1 位为 1 1 1 时满足 a [ i ] ∈ [ 2 k − x , 2 k + 1 − x − 1 ] a[i]\in[2^k-x,2^{k+1}-x-1] a[i][2kx,2k+1x1] i i i 对答案的贡献为 2 k 2^k 2k

于是考虑开 20 20 20 个树状数组,编号为 i i i 的树状数组的第 j j j 位表示有多少 x x x 满足 a [ x ] m o d    2 i + 1 a[x]\mod 2^{i+1} a[x]mod2i+1 的值为 j − 1 j-1 j1,树状数组支持的操作是求前缀和,那么第 k k k 位对答案的贡献变可以转化为 ( q u e r y ( 2 k + 1 − x − 1 ) − q u e r y ( 2 k − x − 1 ) ) × 2 k (query(2^{k+1}-x-1)-query(2^k-x-1))\times 2^k (query(2k+1x1)query(2kx1))×2k,再利用循环节的性质处理一下负数的情况即可。

好巧妙的思路qwq

#include<bits/stdc++.h>
#define ll long long
#define ff(i,s,e) for(int i=(s);i<=(e);++i)
using namespace std;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=1e5+5,M=(1<<20)+5;
int n,q,a[N];
int len[22],t[22][M];
inline int lowbit(int x){return x&(-x);}
inline void upd(int pos,int x,int val){
	++x;
	for(int i=x;i<=len[pos];i+=lowbit(i)) t[pos][i]+=val;
}
inline int query(int pos,int x){
	int res=0;++x;
	for(int i=x;i;i-=lowbit(i)) res+=t[pos][i];
	return res;
}
signed main(){
	n=read(),q=read();
	ff(i,0,19) len[i]=(1<<i+1);
	ff(i,1,n){
		a[i]=read();
		ff(j,0,19) upd(j,a[i]%(1<<j+1),1);
	}
	int op,x,y;
	while(q--){
		op=read(),x=read(),y=read();
		if(op==1){
			ff(j,0,19) upd(j,a[x]%(1<<j+1),-1),upd(j,y%(1<<j+1),1);
			a[x]=y;
		}
		else{
			ll ans=0;
			ff(j,0,19){
				if((y&(1<<j))==0) continue;
				int l=(1<<j),r=(1<<j+1)-1;
				l=(l-1-x+(1<<20))%(1<<j+1);
				r=(r-x+(1<<20))%(1<<j+1);
			//	cout<<l<<' '<<r<<endl;
				if(l<=r) ans+=(1ll*(query(j,r)-query(j,l))<<j);
				else ans+=(1ll*(query(j,len[j]-1)+query(j,r)-query(j,l))<<j);
			}
			printf("%lld\n",ans);
		}
	}
	return 0;
} 

相关文章:

  • 无胁科技-TVD每日漏洞情报-2022-8-30
  • Java8 特性(一):函数、Lambok、Stream
  • 定时器(Quartz)
  • 神经网络实现线性回归,神经网络是回归算法吗
  • MFC调用VLC库播放中文路径导致崩溃的问题
  • 微信公众号搜题功能接口
  • 5.java不同方法的区别(构造方法,实例方法,类方法,static关键字)
  • 无胁科技-TVD每日漏洞情报-2022-8-31
  • 力扣-221题 最大正方形(C++)- dp
  • 信号量(信号灯) -----//目的:实现共享内存的多个进程之间同步
  • JS解决contenteditable=“true“的光标位置放到最后
  • 使用Qt的WebSocket模块小常识
  • 前端ES5,ES6模块Demo
  • 2022/08/31 吉软 JSP的基本使用
  • Nginx--Rewrite重写
  • [PHP内核探索]PHP中的哈希表
  • java第三方包学习之lombok
  • js递归,无限分级树形折叠菜单
  • PHP面试之三:MySQL数据库
  • React系列之 Redux 架构模式
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • swift基础之_对象 实例方法 对象方法。
  • Tornado学习笔记(1)
  • Vue.js 移动端适配之 vw 解决方案
  • 笨办法学C 练习34:动态数组
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 工作手记之html2canvas使用概述
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 简析gRPC client 连接管理
  • 算法---两个栈实现一个队列
  • 最近的计划
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​水经微图Web1.5.0版即将上线
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #Z0458. 树的中心2
  • #宝哥教你#查看jquery绑定的事件函数
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (过滤器)Filter和(监听器)listener
  • (南京观海微电子)——COF介绍
  • (一)基于IDEA的JAVA基础1
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)树状数组
  • .NET 表达式计算:Expression Evaluator
  • .Net 高效开发之不可错过的实用工具
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NetCore项目nginx发布
  • .net的socket示例
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .net中调用windows performance记录性能信息
  • .NET中使用Redis (二)
  • @Autowired多个相同类型bean装配问题
  • [android] 天气app布局练习