GYM 100883 E.xortion(字典树)

来源:互联网 发布:数据联邦 编辑:程序博客网 时间:2024/05/02 18:50

Description
给出一个长度为n的序列a[i],q次查询,每次查询给出一个x,求i使得a[i]^x最大
Input
第一行一整数T表示用例组数,每组用例首先输入两个整数n和q表示序列长度和查询数,之后n个整数a[i]表示该序列,最后q行每行一个整数x表示查询(1<=n<=1e5,1<=q<=3e5,a[i],x不会超过32位整型)
Output
对于每次查询,输入最小的i满足a[i]^x最小
Sample Input
1
3 3
3 1 2
4
5
6
Sample Output
1
3
2
Solution
字典树裸题,把所有a[i]拆成32位二进制建字典树,对于每个x,同样拆成32位二进制在字典树上查询,如果当前为是x,则在字典树上找这一层是否有x^1,如果有就从x^1往下一层走,否则只能从x往下一层走,这样找到终点就找到了a[i]使得a[i]^x最大,因为要输出的是下标所以拿map存一下a[i]和i的对应就好
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define maxn 111111int chd[maxn*32][2],nn=0,num[maxn*32];void init(){    nn=1;    memset(chd[0],-1,sizeof(chd[0]));}void insert(int x){    int p=0;    for(int i=31;i>=0;i--)    {        int t=(x>>i)&1;        if(chd[p][t]==-1)        {            chd[p][t]=nn;            memset(chd[nn],-1,sizeof(chd[nn]));            nn++;        }        p=chd[p][t];    }}int find(int x){    int p=0;    int ret=0;    for(int i=31;i>=0;i--)    {        int t=((x>>i)&1)^1;        if(chd[p][t]==-1)t^=1;        p=chd[p][t];        ret<<=1;        ret|=t;    }    return ret;}map<int,int>M;  int T,n,q;int main(){    int res=0;    scanf("%d",&T);    while(T--)    {        init();        M.clear();        scanf("%d%d",&n,&q);        for(int i=1;i<=n;i++)        {            int a;            scanf("%d",&a);            if(M.find(a)==M.end())M[a]=i,insert(a);        }        while(q--)        {            int a;            scanf("%d",&a);            printf("%d\n",M[find(a)]);        }        if(T)printf("\n");    }    return 0;}
0 0
原创粉丝点击