1. 程式人生 > >Xor Sum (01字典樹)基礎的字典樹題目

Xor Sum (01字典樹)基礎的字典樹題目

初學字典樹的可以拿這道題練練手。

題目連結:傳送門

題目大意:給你n個數,有m次詢問,每次給個數,問:這個數與n個數中的哪個數的異或值最大,輸出它。

給大家兩種寫法;
1。陣列的寫法:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
//typedef __int64 ll;
typedef long long ll;

const int M = 55;
const int N = M*1e5;

struct Node
{
    ll val;
    int
l; int r; void clear() { l = r = -1; } } node[N]; int p; ll a, t[M]; void insert (int& root, int d, ll u) { if (root == -1) { root = p++; node[root].clear(); } if (d == -1) { node[root].val = u; return; } if
(u & t[d]) insert(node[root].r, d - 1, u); else insert(node[root].l, d - 1, u); } void query(int root, int d, ll u) { if (d == -1) { printf("%lld\n", node[root].val); return; } if (((u & t[d]) && node[root].l != -1) || node[root].r == -1
) query(node[root].l, d - 1, u); else query(node[root].r, d - 1, u); } int main () { int cas, n, m; scanf("%d", &cas); t[0] = 1; for (int i = 1; i < 55; i++) t[i] = t[i-1] * 2; for (int i = 1; i <= cas; i++) { p = 0; int root = -1; scanf("%d%d", &n, &m); for (int j = 0; j < n; j++) { scanf("%lld", &a); insert(root, 50, a); } printf("Case #%d:\n", i); for (int j = 0; j < m; j++) { scanf("%lld", &a); query(root, 50, a); } } return 0; }

2。指標的寫法:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;

ll a,wei[56];
struct node
{
    node *left,*right;
    bool l,r;
    ll data;
    void clean()
    {
        l=0;
        data=0;
        r=0;
    }
};
void build(node *head,int f)
{
    if(f==-1)
    {
        head->data=a;
        return ;
    }
    if(a&wei[f])
    {
        if(head->r==0)
        {
            head->r=1;
            head->right=new node;
            head->right->clean();
        }
        build(head->right,f-1);
    }
    else
    {
        if(head->l==0)
        {
        head->l=1;
            head->left=new node;
            head->left->clean();
        }
        build(head->left,f-1);
    }
}
void query(node *head,ll f)
{
    if(f==-1)
    {
        printf("%lld\n",head->data);
        return ;
    }
    //printf("                   fjhd\n");
    if(((a&wei[f])&&head->l==1)||head->r==0)
        query(head->left,f-1);
    else query(head->right,f-1);
}
int main()
{
    int t,tt=1;
    wei[0]=1;
    for(int i=1; i<=55; i++)
        wei[i]=wei[i-1]*2;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        node *head=new node;
        head->clean();
        for(int i=0; i<n; i++)
        {
            scanf("%lld",&a);
            build(head,50);
        }
        printf("Case #%d:\n",tt++);
        for(int i=0; i<m; i++)
        {
            scanf("%lld",&a);
            query(head,50);
        }
    }
    return 0;
}