题目大意:给你n个数,让你找区间里面所有数或 起来大于区间里面最大数的区间个数。
思路:反向思维,找出不符合的区间然后用总数减去。我们找出每个数掌控的最左端
和最右端,一个数的掌控区域为,这个区域里的或 为本身。
注意两个相同的数有可能掌控区域一样,记得将区域分段。
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=2*1e5+5; int n,a[N],l[N],r[N]; map<int,int> mp; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),r[i]=n+1; for(int i=0;i<=31;i++) { int res=0; for(int j=1;j<=n;j++) { if((a[j]>>i)&1) res=j; else l[j]=max(l[j],res); } } for(int i=1;i<=n;i++) { l[i]=max(l[i],mp[a[i]]); mp[a[i]]=i; } for(int i=0;i<=31;i++) { int res=n+1; for(int j=n;j>=1;j--) { if((a[j]>>i)&1) res=j; else r[j]=min(r[j],res); } } ll ans=(ll) n*(n+1)/2; for(int i=1;i<=n;i++) ans-=(ll)(i-l[i])*(r[i]-i); printf("%I64d ",ans); return 0; }