題目鏈接:Subarrays OR
我們以每個數字爲左端點的區間記錄答案。
顯然每個數字向右有效區間不超過30個,因爲每次有效區間肯定會多或上一個1。
所以暴力計算每一位二進制的位置,二分向後跳即可。
AC代碼:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
int n,a[N]; vector<int> v[40],ans;
inline void solve(){
cin>>n; ans.clear();
for(int i=0;i<31;i++) v[i].clear();
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=0;j<31;j++) if(a[i]>>j&1) v[j].push_back(i);
}
for(int i=0;i<31;i++) v[i].push_back(1e9);
for(int i=1;i<=n;i++){
int now=a[i],pos=i;
while(pos<=n){
int mi=1e9; ans.push_back(now);
for(int j=0;j<31;j++) if(!(now>>j&1)){
int tmp=upper_bound(v[j].begin(),v[j].end(),pos)-v[j].begin();
mi=min(mi,v[j][tmp]);
}
if(mi==1e9) break; pos=mi;
now|=a[mi];
}
}
sort(ans.begin(),ans.end()),ans.erase(unique(ans.begin(),ans.end()),ans.end());
printf("%d\n",ans.size());
}
signed main(){
int T; cin>>T; while(T--) solve();
return 0;
}