传送门
考试的时候卡了一会儿。
显然这个答案只跟二进制位为1的数量有关。
还有一个显然的结论。
对于一个区间
[
l
,
r
]
[l,r]
[l,r],如果其中单个数二进制位为1的数量最大值不到区间所有数二进制位为1的数量之和的一半即
m
a
x
n
∗
2
≤
s
u
m
maxn*2\le sum
maxn∗2≤sum,并且sum是偶数那么这个区间是好的。
继续考虑,如果我们枚举左端点l和右端点r,那么当
s
u
m
[
r
0
]
−
s
u
m
[
l
−
1
]
≥
64
sum[r_0]-sum[l-1]\ge 64
sum[r0]−sum[l−1]≥64之后,如果保持
l
l
l不变,
r
0
≤
r
≤
n
r_0\le r\le n
r0≤r≤n时的答案可以直接通过前缀和预处理求出。
这样总时间复杂度是
O
(
n
∗
64
)
O(n*64)
O(n∗64)
代码:
#include<bits/stdc++.h>
#define N 300005
#define ll long long
using namespace std;
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n;
ll a[N],sum[N],sum1[N],sum2[N],ans=0;
inline ll lowbit(ll x){return x&-x;}
inline int calc(ll x){
int ret=0;
while(x)x-=lowbit(x),++ret;
return ret;
}
int main(){
n=read(),sum2[0]=1;
for(int i=1;i<=n;++i)sum[i]=sum[i-1]+(a[i]=calc(read()));
for(int i=1;i<=n;++i)sum1[i]=sum1[i-1]+(sum[i]&1);
for(int i=1;i<=n;++i)sum2[i]=sum2[i-1]+((sum[i]&1)^1);
for(int r=1;r<=n;++r){
ll maxn=a[r];
int low=max(1,r-64);
for(int l=r;l>=low;--l){
maxn=max(maxn,a[l]);
if((maxn<<1)<=(sum[r]-sum[l-1])&&(sum[r]&1)==(sum[l-1]&1))++ans;
}
if(low==1)continue;
ans+=sum[r]&1?sum1[low-2]:sum2[low-2];
}
cout<<ans;
return 0;
}