题面
题意:给出一个序列,问有多少个区间满足(该区间的gcd)xor(区间或)=k。
n,k≤5e5。
像我这种没有常识,数据结构想不出就想分治+数据结构的蒟蒻自然是想不出的。
显然,当右端点r确定了后,不同区间或与gcd都只有logN种,且相同的一段的区间的左端点为一个区间。我们就维护这logN段就可以了。
从小到大枚举r,先更新这logN个区间,再单调地统计答案就可以了。
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const int N=500010;
int n,k,c[N];
LL ans;
int gcd(int x,int y)
{
if(!y)
return x;
return gcd(y,x%y);
}
int work(int x,int y,int op)
{
if(!op)
return (x|y);
return gcd(x,y);
}
struct yy
{
int tp,l[N],r[N],b[N],ops;
void add(int x,int pos)
{
for(int i=1;i<=tp;i++)
b[i]=work(b[i],x,ops);
tp++;
l[tp]=r[tp]=pos;
b[tp]=x;
}
void down()
{
int now=1;
for(int i=2;i<=tp;i++)
{
if(b[now]!=b[i])
{
l[++now]=l[i];
b[now]=b[i];
}
r[now]=r[i];
}
tp=now;
}
}f,g;
void getans()
{
int h1=1,h2=1;
while(1)
{
if(f.r[h1]>g.r[h2])
{
if((f.b[h1]^g.b[h2])==k)
ans+=g.r[h2]-max(f.l[h1],g.l[h2])+1;
h2++;
}
else
{
if((f.b[h1]^g.b[h2])==k)
ans+=f.r[h1]-max(f.l[h1],g.l[h2])+1;
if(h1==f.tp&&h2==g.tp)
break;
h1++;
}
}
}
int main()
{
f.ops=1;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
int hy;
scanf("%d",&hy);
f.add(hy,i);
f.down();
g.add(hy,i);
g.down();
getans();
}
cout<<ans<<endl;
return 0;
}