想了好长时间。。。。
最后看了dyf的题解直接拜到在地上了。
首先注意一下对于从一个固定起点计算and值,计算出来的结果一定是单调不下降的,并且只会有31种可能(2^31)!!!
xor值很好计算,做个前缀xor,我们可以O(1)得到区间的xor值
那么枚举and的起点,不断二分出and变化的位置,问题就变成询问区间内有多少xor值为固定值的问题了。
代码
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Maxn=100005; int n,a[Maxn],c[Maxn],ad[Maxn][20],st[Maxn*2]; int l,r,mid,w,i,j,k,tot,cnt,d,x1,x2,t; struct arr { int data,num; bool operator <(const arr &a)const { return (data<a.data)||(data==a.data && num<a.num); } } p[Maxn]; struct query { int l,r,x; bool operator <(const query &a)const { return x<a.x; } } qy[Maxn*40]; void build(){ for (i=1;i<=n;i++) ad[i][0]=a[i]; for (j=1;j<18;j++) for (i=1;i<=n-(1<<(j-1));i++) ad[i][j]=(ad[i][j-1]&ad[i+(1<<(j-1))][j-1]); } int get(int l,int r){ int t=st[r-l+1]; return (ad[l][t]&ad[r-(1<<t)+1][t]); } int main(){ freopen("hack.in","r",stdin); freopen("hack.out","w",stdout); scanf("%d",&n); for (i=0;i<18;i++) st[1<<i]=i; for (i=1;i<=n;i++) if (st[i]==0) st[i]=st[i-1]; for (i=1;i<=n;i++){ scanf("%d",&a[i]); p[i].data = p[i-1].data^a[i]; p[i].num = i; } build(); for (i=1;i<=n;i++){ d=2147483647; for (r=i-1;r<n;r=w){ d&=a[r+1]; qy[++tot].l=r+1; l=r+1; r=n; w=r+1; while (l<=r){ mid=(l+r)>>1; t=get(i,mid); if (t==d) l=mid+1, w=mid; else r=mid-1; } qy[tot].r=w; qy[tot].x=(d^p[i-1].data); } } sort(qy+1,qy+tot+1); sort(p+1,p+n+1); long long ans=0; for (i=1,j=1;i<=n;){ while (i<=n&&j<=tot&&p[i].data!=qy[j].x){ while (j<=tot && p[i].data>qy[j].x) j++; while (i<=n && p[i].data<qy[j].x) i++; } for (cnt=0;i<=n&&p[i].data==qy[j].x;i++) c[++cnt]=p[i].num; for (k=j;j<=tot&&qy[j].x==qy[k].x;j++){ x1=lower_bound(c+1,c+cnt+1,qy[j].l)-c; x2=upper_bound(c+1,c+cnt+1,qy[j].r)-c; ans+=(long long)x2-x1; } } printf("%I64d\n",ans); return 0; }