Tony's Log

Algorithms, Distributed System, Machine Learning

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

New techniques learnt: Trie can be used for some XOR problems. The basic idea: we build a MSB->LSB prefix Trie of all numbers; then query greedily: find an existing XOR-diff bit at each target bit index.

I found a clean and easy-to-understand code on LeaderBoard, from user pedrosorio 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include <set>
#include <string>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;

#define MAX_NODE 100000
#define MAX_MASK 32768

struct Node
{
    vector<int> inxes;
    Node *child[2]; // 0 - left, 1 - right
    Node()
    {
        child[0] = child[1] = nullptr;
    }
};

void insert(Node *root, int val, int inx)
{
    int mask = 1 << 14;
    int branch;
    Node *p = root;
    while (mask > 0)
    {
        branch = (mask & val) ? 1 : 0;        
        if (p->child[branch] == nullptr)
            p->child[branch] = new Node();
        p = p->child[branch];
        p->inxes.push_back(inx);
        mask >>= 1;
    }
}

void treeDelete(Node *root)
{
    if (root)
    {
        treeDelete(root->child[0]);
        treeDelete(root->child[1]);
        delete root;
    }
}

//    If any existed index in inds is within [p, q]
bool inRange(vector<int> &inds, int p, int q)
{
    int min = 0, max = inds.size() - 1;
    int vmin = inds[min], vmax = inds[max];
    
    int mid, vmid;
    if (vmin > q || vmax < p) return false;
    if (vmin >= p || vmax <= q) return true;
    
    //    Binary search
    //    we need it, because [p,q] may fall into a gap
    while (max > min + 1)
    {
        mid  = (max + min) / 2;
        vmid = inds[mid];
        if (vmid < p)
            min = mid;
        else if (vmid > q)
            max = mid;
        else
            return true;
    }
    
    return false;
}

int treeMaxOr(Node *root, int a, int p, int q)
{
    int mask = 1 << 14, branch, ret = 0;
    Node *ptr = root;
    while (mask > 0)
    {
        branch = (mask & a) ? 0 : 1;
        if (ptr->child[branch] &&
            inRange(ptr->child[branch]->inxes, p, q))
        {
            ret += mask; // found a diff. 
        }
        else
        {
            branch = 1 - branch;
        }
        ptr = ptr->child[branch];
        mask >>= 1;
    }
    return ret;
}

int main()
{
    int t; cin >> t;
    while (t--)
    {
        Node *root = new Node();
        int n, q; cin >> n >> q;
        for (int i = 0; i < n; i++)
        {
            int x; cin >> x;
            insert(root, x, i + 1);
        }
        while (q--)
        {
            int a, p, q; cin >> a >> p >> q;
            cout << treeMaxOr(root, a, p, q) << endl;
        }
        treeDelete(root);
    }
    return 0;
}
View Code

 A more important lesson learnt: visualize the procdure in your mind, and you will probably close to the smart solution!

posted on 2015-06-25 12:35  Tonix  阅读(338)  评论(0编辑  收藏  举报