SPOJ SUBXOR

trie树好题

主要是利用前缀异或

要注意的是首先要插入0

#include <bits/stdc++.h>

typedef long long ll ;
using namespace std;
const int maxn = 1e5+7;

struct node{
    node*ch[2];
    int v;
    node() {v = 0;ch[0] = ch[1] = NULL;}
};
node*root,*rt;
int k;
ll ans;

void insert(int n){
    rt=root;
    for(int level=20;level>=0;level--){
        int id=(n>>level)&1;
        if(rt->ch[id]==NULL) 
            rt->ch[id]=new node();
        rt=rt->ch[id];
        rt->v++;
    }
}

void query(node*cur,int h,int n){
    int ll = (k>>h)&1;
    int pp = (n>>h)&1;
    for(int i=0;i<=1;i++){
        if (cur->ch[i] == NULL) continue;
        if((i^pp)<ll) ans+=cur->ch[i]->v;
        if((i^pp)==ll) query(cur->ch[i],h-1,n);
    }
}

int n;
int val[maxn];

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        int v=0;
        ans=0;
        root=new node();
        insert(0);
        for(int i=1;i<=n;i++){
            v=v^val[i];
            query(root,20,v);
            insert(v);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

另一份代码
主要是修改了询问部分
然后时间少了三分之一。。。。

#include <bits/stdc++.h>

typedef long long ll ;
using namespace std;
const int maxn = 1e5+7;

struct node
{
    node*ch[2];
    int v;
    node() {
        v = 0;
        ch[0] = ch[1] = NULL;
    }

};
node*root,*rt;
int k;

void insert(int n)
{
    rt=root;
    for(int level=20;level>=0;level--){
        int id=(n>>level)&1;        
        if(rt->ch[id]==NULL) 
            rt->ch[id]=new node();
        rt=rt->ch[id];
        rt->v++;
    }
}

int query(int n)
{
    rt=root;
    int ans=0;
    for(int level=20;level>=0;level--){
        if(rt==NULL)break;
        int x=(n>>level)&1;
        int y=(k>>level)&1;
        if(y){
            if(rt->ch[x]!=NULL) ans+=rt->ch[x]->v;
            rt=rt->ch[1-x];
        } else rt=rt->ch[x];
    }
    return ans;
}

int n;
int val[maxn];

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",&val[i]);
        int v=0;
        ll ans=0;
        root=new node();
        insert(0);
        for(int i=1;i<=n;i++){
            v=v^val[i];
            ans+=(ll)query(v);
            insert(v);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值