题意
给一个数列
A
A
A,其中
A
x
A_x
Ax可以进化到
A
y
A_y
Ay的条件:
1
)
x
<
y
1)x<y
1)x<y
2
)
A
x
∣
A
x
+
1
∣
A
x
+
2
∣
.
.
.
∣
A
y
<
M
2)A_x|A_{x+1}|A_{x+2}|...|A_y<M
2)Ax∣Ax+1∣Ax+2∣...∣Ay<M
思路
我们维护一个队列,可以知道它是一直往右的。
每次往队尾加入一个数,然后一直踢掉队头直到满足当前队列中的或值
<
M
<M
<M(因为当前如果不满足或值
<
M
<M
<M的话那么队头的数就不能进化到后面的数)
答案累加
t
a
i
l
−
h
e
a
d
tail-head
tail−head,代表前面的每个数都能进化到当前队尾的数。
代码
#include<cstdio>
#include<algorithm>
int N, M;
long long ans;
int a[100001], v[100001];//v记录每一位上1的个数
void insert(int x) {
for (int i = 0; i <= 30; i++)
v[i] += (x >> i) & 1;
}
void del(int x) {
for (int i = 0; i <= 30; i++)
v[i] -= (x >> i) & 1;
}
int getK() {
int r = 0;
for (int i = 0; i <= 30; i++)
r += (std::min(v[i], 1) << i);
return r;
}
int main() {
scanf("%d %d", &N, &M);
for (int i = 1; i <= N; i++)
scanf("%d", &a[i]);
int head = 1;
for (int i = 1; i <= N; i++) {
insert(a[i]);
while (getK() >= M && head < i)
del(a[head++]);
ans += i - head;
}
printf("%lld", ans);
}