# 2035: Cafe Bazaar

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

## 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


## 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) {
return;
}
if (s == -1) {
if (check1 (now, d + 1) ) {
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) ) {
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;
}