!codeforces 400E Inna and Binary Logic-yy-(位运算)

来源:互联网 发布:linux如何给文件夹改名 编辑:程序博客网 时间:2024/05/19 00:43

题意:有n个数存放在数组a1[]中,然后数组a1[]生成数组a2[],a2[]生成a3[].....一直生成an[],公式是ai[k]=ai-1[k]&ai-1[k+1],现在如果把初始数据也就是数组a1[]里的某一个数换成另一个数,求所有数组的总和是多少。

分析:既然这里的数组生成公式里用到了位与运算,那么就用位运算来做了。

把数字写成二进制,公式的意思就是说同一数组的相邻数字的对应二进制位相与生成下一数组的一个数字的对应二进制位。先求出不做改变前的总和,然后每次改变通过替换数字与原数字每一位的差异来计算由该二进制位的差异引起的总和的差异,也就是说这里计算的基本单位不是每一个数字,而是数字的每一位。具体过程在草稿纸上画图,把a1[]数组的数字写成二进制形式,然后排成一列,对照每一位来找规律。另外预处理总和不能用模拟的方法O(n^2)似乎会超时,也是用位来计算。

小技巧:1<<i 可以表示第i位二进制位的权,也可以与别的数字相与获取该数字的第i位二进制位,从而判断该数字的这一位是1还是0

代码:

#include<iostream>#include<cstdio>#define N 100005using namespace std;int n,m,a[100005],x,y;long long sum;void init()    //预处理不做改变前的所有数组的和{for(int i=0;(1<<i)<N;i++){int k=1<<i;long long tot=0;for(int j=1;j<=n;j++){if(k&a[j]) tot++;else{sum+=tot*(tot+1)/2*(long long)k;tot=0;}}if(tot) sum+=tot*(tot+1)/2*(long long)k;}}void work(int x,int y)    //当替换第x个数字为y时的总和{for(int i=0;(1<<i)<N;i++){int k=1<<i;if((k&y)==(k&a[x])) continue;long long l=0,r=0;for(int p=x-1;p>0;p--)    if(k&a[p]) l++;  else break;for(int p=x+1;p<=n;p++)    if(k&a[p]) r++;  else break;long long tmp=(l*r+l+r+1)*(long long)k;if(k&y) sum+=tmp;else sum-=tmp;}}int main(){cin>>n>>m;sum=0;for(int i=1;i<=n;i++) cin>>a[i];init();while(m--){cin>>x>>y;work(x,y);cout<<sum<<endl;a[x]=y;}}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ps超出2g存不了怎么办 qq帐号不记得了怎么办 苹果手机wifi密码输错怎么办 qq搜索关键字屏蔽了怎么办 手机数据被屏蔽了怎么办 ea账号安全问题答案忘了怎么办 电脑用户账户密码忘记了怎么办 公司名字审核通过剩下怎么办 抖音一直在审核怎么办 平板电脑显示ipad已停用怎么办 违章车型与实际车型不符怎么办 网购与实物不符怎么办 内网ip地址丢失怎么办 转账户名写错了怎么办 工资卡开户写错公司名称怎么办 商标跟别人重了怎么办 不受信任的应用打不开怎么办 oppo手机安全证书过期怎么办 网站安全证书有问题怎么办 公章圆圈摔坏了怎么办 高风险办税人员怎么办 公司因担保被起诉怎么办 借公司钱被起诉怎么办 qq群管理员满了怎么办 微信公众号搜索不到怎么办 微信名字改不了怎么办 微信号第一次限制登录怎么办 微信第一次限制登录怎么办 老板不回我微信怎么办 微信号换手机号了怎么办 电话被对方拉黑怎么办 微信被好友拉黑了怎么办 微信收藏删了怎么办 如果忘记支付宝登录手机号码怎么办 支付宝登录密码忘记了怎么办 支付宝账户名忘记了怎么办 搜索qq号搜不到怎么办 微信号手机号码换了怎么办 起诉以后没有被告人住址怎么办 农村老人走丢了怎么办 读在职博士工作单位不支持怎么办