Problem:
Give a series of IP segments, for example, [0.0.0.1-0.0.0.3], [123.234.232.21-123.245.21.1]...
Now there is a new IP, find which IP segment it's in ?
Solution:
First, we could map the ends of IP segments into some intervals, since the IP address could be represented by a unsigned int. This is called discretization.
Second, setup the segment tree. Every leaf node is [x, x+1], it means whether an IP segment includes the part. We could use a vector<int> to record the interval index for searching. So the core code is:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
using namespace std;
class Interval {
public:
int l, r;
Interval(int ll = 0, int rr = 0) : l(ll), r(rr) {}
};
class Node {
public:
int l, r;
Node *lc, *rc;
vector<int> IPs;
Node(int ll = 0, int rr = 0) : l(ll), r(rr), lc(NULL), rc(NULL) {}
};
Node* build(int l, int r) {
Node *root = new Node();
root->l = l, root->r = r;
if (l + 1 >= r)
return root;
int mid = (l + r) / 2;
root->lc = build(l, mid);
root->rc = build(mid, r);
return root;
}
void insert(Node* root, int l, int r, int idx) {
if (l <= root->l && r >= root->r) {
root->IPs.push_back(idx);
return;
}
int mid = (root->l + root->r) / 2;
if (l < mid) // Take care here!
insert(root->lc, l, mid, idx);
if (r > mid) // Take care here!
insert(root->rc, mid, r, idx);
}
void search(Node* root, int l, int r, vector<int>& res) {
if (r <= root->r && l >= root->l) {
for (int i = 0; i < root->IPs.size(); ++i)
res.push_back(root->IPs[i]);
}
int mid = (root->l + root->r) / 2;
if (r <= mid)
search(root->lc, l, mid, res);
if (l >= mid)
search(root->rc, mid, r, res);
}
int main()
{
Node* rt = build(1, 7);
Interval inters[] = {Interval(1,3),Interval(2,4),Interval(1,5), Interval(5,7)};
int size = sizeof(inters) / sizeof(inters[0]);
for (int i = 0; i < size; ++i)
insert(rt, inters[i].l, inters[i].r, i);
vector<int> res;
search(rt, 2, 3, res);
return 0;
}