SCU 4103 function(前缀处理+字典树)

来源:互联网 发布:2016最火的网络歌曲 编辑:程序博客网 时间:2024/05/20 07:31
A - function
Time Limit:0MS     Memory Limit:0KB     64bit IO Format:%lld & %llu
Submit Status Practice SCU 4103

Description

Time Limit: 8000 MS    Memory Limit: 131072 K 

Description

Given a set of n integers: num={num1,num2,.....,num n} and an integer m.we define a function AA(num,m) as below: AA(num,m)={[l,r]| (l<=r) && (num[l]^num[l+1]….^num[r])<=m }.Your task is to calculate the number of element of AA(num,m).

Input

The first line contains the number of test cases.For every test,the input consists of two lines.The first line contains two integers n and m. There are n integers in the second line.limit:1<=n<=10^5, 0<=num[i], m<2^31;

Output

For each test case just output one integer in one line.

Sample Input

22 31 42 34 5

Sample Output

11

Source

456@scuacmSichuan University Programming Contest 2012 Preliminary



题意:给定n个数,问有多少个区间【l,r】里面所有数异或的结果小于m

题解:字典树,对于区间[L,R]的异或值,是满足区间减法的。即a[L] ^ a[L + 1] ^ ... ^ a[R] = (a[1] ^ a[2] ^ .. ^ a[L - 1]) ^ (a[1] ^ a[2] ^ .. ^ a[R]) (因为a[1]... a[L - 1]全部出现了2次,根据异或性质,是抵消的)。所以将a[1] ^ ... a[i]的结果插入trie树中,类似于前缀和的形式,每次对于一个新的a[i + 1],查询a[1],(a[1] ^ a[2]) .. (a[1] ^ .. ^ a[i])有多少个与现在 (a[1] ^ .. ^ a[i+1])异或结果<=M


#include<stdio.h>struct tire{    int next[2],cou;    void init()    {        cou=0;        next[0]=next[1]=-1;    }}tree[3200008];int all,n,m;void myinsert(int x){    int id=0,i,temp;    for(i=30;i>=0;i--)    {        tree[id].cou++;        temp=(1<<i)&x?1:0;        if(tree[id].next[temp]==-1)        {            tree[++all].init();            tree[id].next[temp]=all;        }        id=tree[id].next[temp];    }    tree[id].cou++;}int myfind(int now,int cur,int id){    int temp=0;    if(!cur) return now<=m?tree[id].cou:0;    if((now|((1<<cur)-1))<=m) return tree[id].cou;    if((now&(~((1<<cur)-1)))>m) return 0;    if(tree[id].next[0]!=-1) temp+=myfind(now,cur-1,tree[id].next[0]);    if(tree[id].next[1]!=-1) temp+=myfind(now^(1<<(cur-1)),cur-1,tree[id].next[1]);    return temp;}int main(){    int t,i,now,x;    long long res;    scanf("%d",&t);    while(t--)    {        tree[all=0].init();        scanf("%d%d",&n,&m);        myinsert(0);        for(res=now=i=0;i<n;i++)        {            scanf("%d",&x);            now^=x;            res+=myfind(now,31,0);            myinsert(now);        }        printf("%I64d\n",res);    }    return 0;}


0 0