直接考虑每个位置成为最右边的最大值的位置,统计不合法区间,补集转化一下就好啦。
复杂度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*(ll)(n+1)>>1)-ans); return 0; }