题意:
给你一个数组,问你有多少个区间[L, R]满足区间内的值or运算后大于区间最大值。
题解:
使得取或后的值大于最大值,则区间内一定有数包含最大值不包含的位。
那么逆向思考,我们只要求出区间内的数只有最大值包含的位的区间个数, 然后用所有区间数减即可。
枚举每个i,假设他是最大值,然后看从左从右可以扩展到多远,即可。
用DP记录一下即可。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif
#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;
const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 2e5 + 5;
int a[MAXN];
int l[MAXN][33], r[MAXN][33];
unordered_map<int, int> vis;
int main() {
#ifdef LOCAL
freopen ("input.txt", "r", stdin);
#endif
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) {
for(int j = 0; j < 32; j++) {
if(a[i] >> j & 1) l[i][j] = i;
else l[i][j] = l[i - 1][j];
}
}
for(int i = 0; i < 32; i++) r[n + 1][i] = n + 1;
for(int i = n; i >= 1; i--) {
for(int j = 0; j < 32; j++) {
if(a[i] >> j & 1) r[i][j] = i;
else r[i][j] = r[i + 1][j];
}
}
ll ans = 0;
for(int i = 1; i <= n; i++) {
int L = 0, R = n + 1;
for(int j = 0; j < 32; j++) {
if(a[i] >> j & 1) continue;
L = max(L, l[i][j]);
R = min(R, r[i][j]);
}
L = max(L, vis[a[i]]);
vis[a[i]] = i;
ans += (ll)(i - L) * (R - i);
}
printf("%lld\n", (ll) n * (n + 1) / 2 - ans);
return 0;
}