CSU-2035 Cafe Bazaar

2035: Cafe Bazaar

Submit Page      Summary      Time Limit: 3 Sec       Memory Limit: 512 Mb       Submitted: 67       Solved: 15    

Description

Having a heavy load on its servers, Cafe Bazaar keeps a daily log of the traffic to its server for performance optimization and statistical purposes. The IP addresses in the log for each day is stored in a database either in the IP-range format or CIDR format, both explained below. The IP database software uses a new version of the Internet Protocol (IP) called IPv5. IPv5 provides more IP addresses by extending the number of address bits from 32 in the IPv4 to 40. Precisely, each IP address in the IPv5 is a 40-bits numerical label assigned to each device connected to the Internet. Each IP address can be represented as a sequence of 5 numbers, called bytes, each having a decimal value ranging from 0 to 255. IP addresses are often written in the dot-decimal notation, for example “134.172.16.254.1”. The notation consists of five bytes of the IP address expressed in decimal and separated by periods. Note that in this notation the leading zero bytes are not removed. For example, the correct representation of an address with numerical value 0 is “0.0.0.0.0”. Classless Inter-Domain Routing (CIDR) is a way of specifying a range of IP addresses. A CIDR looks like a normal IP address except that it ends with a slash followed by a number. The CIDR y/x in which y is an IP address and x is an integer from 0 to 40 (inclusive), shows a range of addresses whose x leftmost bits are equal to the x leftmost bits of y. The remaining bits are free to be either 0 or 1. To guarantee a unique representation for each range, the 40 − x rightmost bits of y should be equal to 0. The IP-range format is another way of specifying a range of IP addresses. A range in this format is represented by its first and last address in dot decimal notation, separated by a dash (-). The first address is not larger than the last address assuming IP addresses are 5-digit numbers in the base 256. For example, “128.192.168.200.0/32” is a CIDR in which the first 32 bits (4 bytes, “128.192.168.200”) are the same for all addresses in the range, and only the last byte can be different. The same range can be represented in the IP-range format by “128.192.168.200.0-128.192.168.200.255”. Due to attracting many customers from all around the world and continuous service for many years, the IP database is getting larger and larger. Thus, Cafe Bazaar plans to reduce the number of entries in the database by representing the existing ranges using the minimum number of CIDRs. The new CIDRs should not include any IP address that does not belong to the IP database. Your task is to solve this challenging problem.

Input

There are multiple test cases in the input. For each test case, the first line contains an integer n, the number of IP ranges (1 ⩽ n ⩽ 100) in the IP database. Each of the next n lines contains an IP range, either in the CIDR format or in the IP-range format. The input terminates with a line containing “0” which should not be processed.

Output

For each test case, print the minimum number of CIDRs which represent the whole IP database; followed by the list of CIDRs in an increasing order of IP values.

Sample Input

2
128.192.168.10.0/32
128.192.168.11.0-128.192.168.11.255
1
128.192.168.200.0-128.192.168.200.10
0

Sample Output

1
128.192.168.10.0/31
3
128.192.168.200.0/37
128.192.168.200.8/39
128.192.168.200.10/40

Hint

Source

ATRC2017


#include <cstdio>
#include<map>
#include<algorithm>
#include<cstring>
#include<iostream>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<int, LL>PIL;
typedef pair<LL, int> PLI;
typedef pair<LL, LL> PLL;
const int MX = 1e2 + 5;
const int MXM = MX * 40;

vector<PLI>ver;

struct Trie {
    int nxt[MXM][2], cnt[MXM];
    int root, rear;
    int new_node() {
        cnt[++rear] = 0;
        memset (nxt[rear], 0, sizeof (nxt[rear]) );
        return rear;
    }
    void init () {
        rear = 0;
        root = new_node();
    }
    void insert (LL x) {
        int now = root, tmp;
        for (int i = 40; i; i--) {
            tmp = x >> (i - 1) & 1;
            if (!nxt[now][tmp]) nxt[now][tmp] = new_node();
            now = nxt[now][tmp];
            cnt[now]++;
        }
    }
    void query() {
        dfs (root, 0, 0, -1);
    }
    void add (LL x, int y) {
        for (int i = y + 1; i <= 40; i++) x <<= 1;
        ver.push_back (PLI (x, y) );
    }
    bool check1 (int now, int d) {
        int now1 = now, now2 = now;
        for (int i = d; i <= 40; i++) {
            if (nxt[now1][0] == 0 || nxt[now2][1] == 0) return 0;
            now1 = nxt[now1][0];
            now2 = nxt[now2][1];
        }
        return 1;
    }
    bool check2 (int now, int d, int s) {
        for (int i = d; i <= 40; i++) {
            if (nxt[now][s] == 0) return 0;
            now = nxt[now][s];
        }
        return 1;
    }
    void dfs (int now, int d, LL val, int s) {
        if (d == 40) {
            add (val, d);
            return;
        }
        if (s == -1) {
            if (check1 (now, d + 1) ) {
                add (val, d);
                return;
            }
            if (nxt[now][0] && nxt[now][1]) {
                dfs (nxt[now][0], d + 1, val << 1, 0);
                dfs (nxt[now][1], d + 1, val << 1 | 1, 1);
            } else if (nxt[now][0]) dfs (nxt[now][0], d + 1, val << 1, -1);
            else dfs (nxt[now][1], d + 1, val << 1 | 1, -1);
        } else {
            if (check2 (now, d + 1, s) ) {
                add (val, d);
                return;
            }
            if (nxt[now][s ^ 1] == 0) add ( val << 1 | (s ^ 1), d + 1), dfs (nxt[now][s], d + 1, val << 1 | s, s);
            else dfs (nxt[now][s ^ 1], d + 1, val << 1 | (s ^ 1), s);
        }
    }
} t;

int a[MX], n;
char str[MX];

LL code (int l, int r) {
    LL ret = 0, tmp = 0;
    for (int i = l; i <= r; i++) {
        if (str[i] == '.' || i == r) {
            ret = ret * 256 + tmp, tmp = 0;
            continue;
        }
        tmp = tmp * 10 + str[i] - '0';
    }
    return ret;
}

bool cmp1 (const PLL& p1, const PLL& p2) {
    if (p1.x != p2.x) return p1.x < p2.x;
    return p1.y > p2.y;
}
bool cmp2 (const PLI& p1, const PLI& p2) {
    return p1.x < p2.x;
}
PLL p[MX];

void print (LL x, int y) {
    for (int i = 4; i >= 0; i--) {
        LL tmp = x >> (8 * i) & 255;
        printf ("%lld%c", tmp, i == 0 ? '/' : '.');
    }
    printf ("%d\n", y);
}

int main() {
    //freopen ("in.txt", "r", stdin);
    while (~scanf ("%d", &n), n) {
        ver.clear();
        for (int i = 0, j; i < n; i++) {
            scanf ("%s", str);
            int len = strlen (str);
            for (j = 0; j < len; j++) if (str[j] == '-' || str[j] == '/') break;
            LL l, r;
            if (str[j] == '-') {
                l = code (0, j), r = code (j + 1, len);
            } else {
                l = r = code (0, j);
                int cnt = 0;
                for (++j; j < len; j++) cnt = cnt * 10 + str[j] - '0';
                for (int i = cnt + 1; i <= 40; i++) r |= (1LL << (40 - i) );
            }
            p[i] = PLL (l, r);
        }
        sort (p, p + n, cmp1);
        int pre = 0;
        for (int i = 1; i < n; i++) {
            if (p[i].x - 1 <= p[pre].y) p[pre].y = max (p[pre].y, p[i].y);
            else p[++pre] = p[i];
        }
        for (int i = 0; i <= pre; i++) t.init(), t.insert (p[i].x), t.insert (p[i].y), t.query();
        sort (ver.begin(), ver.end(), cmp2);
        printf ("%d\n", ver.size() );
        for (auto f : ver) print (f.x, f.y);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31759205/article/details/79967877