码迷,mamicode.com
首页 > 其他好文 > 详细

XJOI 异或 (Trie树)

时间:2017-09-07 19:29:18      阅读:142      评论:0      收藏:0      [点我收藏+]

标签:clu   最大   bit   技术分享   printf   等于   节点   res   image   

技术分享

技术分享

这题对我来说真是一块大蛋糕,又是一座大山

大蛋糕是因为算法很好胡

大山是因为我实在是太菜

然后我就在考场上续了两个小时

/-------------------------------------------/

这题算法不算难想,但对我来说挺难打

1.将ai拆成二进制,由高位到低位加入Trie树,不足的补前导0,每个节点的ans统计子树中有多少个值

2.读入区间l,r拆成区间1-r+1,1-l处理

3.search时统计小于limit的数量

4.如果pos的一个子树内异或x最大值之差小于limit,就直接加上ans[pos]

5.如果大于等于limit就递归处理子问题

#include<bits/stdc++.h>
using namespace std;
int a[32],n,m,x,l,r,tot,ch[5000000][2],ans[5000000];
void add(int x){
    int pos=1;
    ans[pos]++;
    for (int i=1; i<=31; i++){
        int j=x/a[i]; x%=a[i];
        if (ch[pos][j]==0) ch[pos][j]=++tot;
        pos=ch[pos][j];
        ans[pos]++;
    }
}
int search(int s,int ii,int x,int limit){
    int pos=s,res=0;
    for (int i=ii; i<=31; i++){
        int j=x/a[i]; x%=a[i];
        if (a[i]<=limit){
            if (ch[pos][j]) res+=ans[ch[pos][j]];
            if (ch[pos][j^1]) res+=search(ch[pos][j^1],i+1,x,limit-a[i]);
            break;
        }
        if (ch[pos][j]) pos=ch[pos][j]; else break;
    }
    return res;
}
int main(){
    tot=1;
    a[31]=1;
    for (int i=30; i>=1; i--) a[i]=a[i+1]*2;
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++){
        scanf("%d",&x);
        add(x);
    }
    while (m--){
        scanf("%d%d%d",&x,&l,&r);
        printf("%d\n",search(1,1,x,r+1)-search(1,1,x,l));
    }
}

XJOI 异或 (Trie树)

标签:clu   最大   bit   技术分享   printf   等于   节点   res   image   

原文地址:http://www.cnblogs.com/Yuhuger/p/7491066.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!