Educational Codeforces Round 12 E Beautiful Subarrays

先转换成异或前缀和,变成询问两个数异或≥k的方案数。

分治然后Trie树即可。

#include<cstdio>
#include<algorithm>
#define N 1000010
#define mid (l+r>>1)
#define ll long long
using namespace std;
int n,k,a[N];ll ans;
struct Trie
{
    int next[N*30][2],tot,sum[N*30];
    void init()
    {
        for(int i=1;i<=tot;i++)
        next[i][0]=next[i][1]=sum[i]=0;
        tot=1;
    }
    void add(int x)
    {
        int now=1;
        for(int i=30;~i;i--)
        {
            int c=(x>>i)&1;
            if(!next[now][c])
            next[now][c]=++tot;
            now=next[now][c];
            sum[now]++;
        }
    }
    int query(int x)
    {
        int now=1,res=0;
        for(int i=30;~i;i--)
        {
            int c=(k>>i)&1,p=(x>>i)&1;
            if(c==0)res+=sum[next[now][!p]];
            now=next[now][p^c];
            if(!now)return res;
        }
        return res;
    }
}t;
void solve(int l,int r)
{
    if(l==r)return;
    t.init();
    for(int i=l;i<=mid;i++)
    t.add(a[i]);
    for(int i=mid+1;i<=r;i++)
    ans+=t.query(a[i]);
    solve(l,mid);
    solve(mid+1,r);
}
int main()
{
    scanf("%d%d",&n,&k);n++;k--;
    for(int i=2;i<=n;i++)
    scanf("%d",&a[i]),a[i]^=a[i-1];
    solve(1,n);
    printf("%lld\n",ans);
}
View Code

 

posted @ 2016-05-10 10:11  xuruifan  阅读(156)  评论(0编辑  收藏  举报