直接考虑每个位置成为最右边的最大值的位置,统计不合法区间,补集转化一下就好啦。
复杂度O(N * 30)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=200005;
unordered_map<int,int> mmp;
int n,a[N],L[N],ex[35],ci[35];
ll ans=0;
int main(){
ci[0]=1;
for(int i=1;i<=30;i++) ci[i]=ci[i-1]<<1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
for(int j=0;j<=30;j++)
if(!(a[i]&ci[j])) L[i]=max(L[i],ex[j]);
else ex[j]=i;
}
fill(ex,ex+33,n+1);
for(int i=n,R;i;i--){
R=n+1;
for(int j=0;j<=30;j++)
if(!(a[i]&ci[j])) R=min(R,ex[j]);
else ex[j]=i;
if(mmp.count(a[i])) R=min(R,mmp[a[i]]);
ans+=(R-i)*(ll)(i-L[i]);
mmp[a[i]]=i;
}
printf("%lld\n",(n*(ll)(n+1)>>1)-ans);
return 0;
}