博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Code Forces 1030E
阅读量:5733 次
发布时间:2019-06-18

本文共 1207 字,大约阅读时间需要 4 分钟。

题目大意

给你n个数,你可以交换一个数的任意二进制位,问你可以选出多少区间经过操作后异或和是0。

思路分析:

根据题目,很容易知道,对于每个数,我们可以无视它的1在那些位置,只要关注它有几个1即可,如果它的1的数量可以通过加减为0,那么这个区间就是合法的。

可以看到,两个数(分别有x,y个1,且x〉y)通过交换位置再进行异或操作,可能获得的新数中1的数量为y-x,y-x+2,y-x+4,...,x+y-2,x+y。

那么对于每一个左端点(l),它的合法右端点(r)的数量为sum[r]-sum[l-1]为偶数的r的个数(sum为前缀和数组)。同时,这个区间还要满足区间内1的数量最多的数(假设它在第k位)要小于sum[k]-sum[l-1]的一半,因为假如说它不满足这一条件的话,那么就没有足够多的1同它相抵消,也就不会合法。

那么我们应该如何避免这种状况呢?

很简单,可能会是不合法右端点的几个点(最多64个)直接暴力做就行了。

代码:

var  a,sum,odd,even:array[0..300000]of longint;  i,j,s,max,n,m:longint;  ans,x:int64;begin  read(n);  for i:=1 to n do  begin    read(x);    while x>0 do    begin      a[i]:=a[i]+x and 1;      x:=x>>1;    end;  end;  for i:=1 to n do  begin    sum[i]:=sum[i-1]+a[i];    odd[i]:=odd[i-1]; even[i]:=even[i-1];    if sum[i]and 1=1 then inc(odd[i]) else inc(even[i]);  end;  for i:=1 to n do    if sum[i-1]and 1=1 then ans:=ans+odd[n]-odd[i-1]      else ans:=ans+even[n]-even[i-1];  writeln(ans);  for i:=1 to n do  begin    if i+64>n then m:=n else m:=i+64;    s:=0; max:=0;    for j:=i to m do    begin      if a[j]>max then max:=a[j];      s:=s+a[j];      if (2*max>s)and(s mod 2=0) then dec(ans);    end;  end;  writeln(ans);end.

 

转载于:https://www.cnblogs.com/WR-Eternity/p/9735488.html

你可能感兴趣的文章
摹客iDoc —— 自动生成你的颜色规范
查看>>
One question per day
查看>>
写给前端应届生的职业规划建议
查看>>
IntelliJ System.out.println() - Cannot resolve method println(java.lang.String)
查看>>
Node.js中的Buffer
查看>>
JavaScript混淆安全加固
查看>>
15 款免费好用的 Mac Apps
查看>>
Logtail提升采集性能
查看>>
浅析SFX脚手架源码
查看>>
Vue+thinkJs博客网站(二)之thinkJs的使用
查看>>
云服务器使用感受
查看>>
js 疑难01 new()
查看>>
菜鸟成长之路04
查看>>
chrome开发者工具使用
查看>>
关于spy-debugger
查看>>
NSCollectionView使用笔记
查看>>
三次握手的误解与错误类比 (RFC 解读)
查看>>
Java爬虫之批量下载LibreStock图片(可输入关键词查询下载)
查看>>
zzz 周刊 - 第1047期
查看>>
密码管理工具 - iPassword
查看>>