DD14. CIDR去重
描述
无类别域间路由(CIDR)是一个用于对IPV4地址进行分类表述的方法。CIDR 路由描述的IP地址组的子网mask长度是可变长度, 例如10.0.0.0/22 表示前22位和10.0.0.0相同的网络地址都被覆盖, 22包含了10.0这前两个字段(0-7位,8-15位)和第三个字段的前6位(16-21,即0b000000**), 涵盖了 10.0.0.*, 10.0.1.*, 10.0.2.*, 10.0.3.* 四组ip地址. 在此前提下请实现IP网络中的一个常用的去重操作: 给定一系列 CIDR 路由地址, 其中没有完全等价的路由, 去掉被重复表示的 CIDR 路由, 即去掉已经被其他CIDR路由表示覆盖的路由地址. 例如 10.0.1.1/32 已经被 10.0.0.0/22覆盖了, 如果路由列表中已经有了后者, 就可以去掉前者.输入描述
k+1行, k表示输入的CIDR路由个数输出描述
n+1行, n表示去重后剩下的CIDR路由个数示例1
输入:
13 192.168.0.0/16 172.24.96.17/32 172.50.137.225/32 202.139.219.192/32 172.24.68.0/24 192.183.125.71/32 201.45.111.138/32 192.168.59.211/32 192.168.26.13/32 172.24.0.0/17 172.24.5.1/32 172.24.68.37/32 172.24.168.32/32
输出:
7 192.168.0.0/16 172.50.137.225/32 202.139.219.192/32 192.183.125.71/32 201.45.111.138/32 172.24.0.0/17 172.24.168.32/32
C++ 解法, 执行用时: 2ms, 内存消耗: 376KB, 提交时间: 2020-10-31
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <string.h> #include <limits.h> #include <cfloat> #include <stack> #include <queue> #include <list> #include <set> #include <map> #include <bitset> #include <cassert> #include <unordered_map> #include <unordered_set> using namespace std; #define mem(flag) memset(flag,0,sizeof(flag)) #define Mem(flag) memset(flag,-1,sizeof(flag)) #define En printf("\n") #define P(a) printf("%d ",a) #define read(a) scanf("%d", &a) #define readll(a) scanf("%lld", &a) #define reads(s) scanf("%s", s) #define Pn(a) printf("%d\n",a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define rep(flag, a, b) for (int flag = (a); flag <= (b); ++flag) #define Rep(flag, a, b) for (int flag = (a); flag >= (b); --flag) const int MAX = 1e5; char buf[MAX][100]; typedef unsigned int uint; int n; uint val[MAX][35]; int tmp[50]; int tnt; struct node { int i, pos; uint val; node (int a = 0, int b = 0, uint c = 0) : i(a), pos(b), val(c) {} }; uint l[MAX], r[MAX]; int idx[MAX]; int main() { read(n); rep (i, 1, n) scanf("%s", buf[i]); rep (i, 1, n) { int as[4]; int key; sscanf(buf[i], "%d.%d.%d.%d/%d\n", &as[0], &as[1], &as[2], &as[3], &key); tnt = 0; bitset<32> ans; rep (j, 0, 3) { bitset<32> zn(as[j]); ans = ans | (zn << ((32 - (j + 1) * 8))); } //printf("%s\n", ans.to_string().data()); int x = 32 - key; l[i] = 0; Rep (j, 31, x) { l[i] += ans[j] * (1 << j); } r[i] = l[i] + (1 << x) - 1; //printf("%s\n%s\n", bitset<32> (l[i]).to_string().data(), bitset<32> (r[i]).to_string().data()); //En; } rep (i, 1, n) idx[i] = i; sort(idx + 1, idx + n + 1, [] (int a, int b) { if (l[a] != l[b]) return l[a] < l[b]; else return r[a] > r[b]; }); vector<int> ans; ans.push_back(idx[1]); rep (i, 2, n) { int t = ans[(int)ans.size() - 1]; int cur = idx[i]; if (r[cur] <= r[t]) continue; else { ans.push_back(cur); } } Pn(ans.size()); sort(ans.begin(), ans.end()); rep (i, 0, (int)ans.size() - 1) printf("%s\n", buf[ans[i]]); return 0; }
C++ 解法, 执行用时: 2ms, 内存消耗: 380KB, 提交时间: 2020-10-31
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <string.h> #include <limits.h> #include <cfloat> #include <stack> #include <queue> #include <list> #include <set> #include <map> #include <bitset> #include <cassert> #include <unordered_map> #include <unordered_set> using namespace std; #define mem(flag) memset(flag,0,sizeof(flag)) #define Mem(flag) memset(flag,-1,sizeof(flag)) #define En printf("\n") #define P(a) printf("%d ",a) #define read(a) scanf("%d", &a) #define readll(a) scanf("%lld", &a) #define reads(s) scanf("%s", s) #define Pn(a) printf("%d\n",a) #define dbg(x) cout << (#x) << " = " << (x) << endl #define rep(flag, a, b) for (int flag = (a); flag <= (b); ++flag) #define Rep(flag, a, b) for (int flag = (a); flag >= (b); --flag) const int MAX = 1e5; char buf[MAX][100]; typedef unsigned int uint; int n; uint val[MAX][35]; int tmp[50]; int tnt; struct node { int i, pos; uint val; node (int a = 0, int b = 0, uint c = 0) : i(a), pos(b), val(c) {} }; uint l[MAX], r[MAX]; int idx[MAX]; int main() { read(n); rep (i, 1, n) scanf("%s", buf[i]); rep (i, 1, n) { int as[4]; int key; sscanf(buf[i], "%d.%d.%d.%d/%d\n", &as[0], &as[1], &as[2], &as[3], &key); tnt = 0; bitset<32> ans; rep (j, 0, 3) { bitset<32> zn(as[j]); ans = ans | (zn << ((32 - (j + 1) * 8))); } //printf("%s\n", ans.to_string().data()); int x = 32 - key; l[i] = 0; Rep (j, 31, x) { l[i] += ans[j] * (1 << j); } r[i] = l[i] + (1 << x) - 1; //printf("%s\n%s\n", bitset<32> (l[i]).to_string().data(), bitset<32> (r[i]).to_string().data()); //En; } rep (i, 1, n) idx[i] = i; sort(idx + 1, idx + n + 1, [] (int a, int b) { if (l[a] != l[b]) return l[a] < l[b]; else return r[a] > r[b]; }); vector<int> ans; ans.push_back(idx[1]); rep (i, 2, n) { int t = ans[(int)ans.size() - 1]; int cur = idx[i]; if (r[cur] <= r[t]) continue; else { ans.push_back(cur); } } Pn(ans.size()); sort(ans.begin(), ans.end()); rep (i, 0, (int)ans.size() - 1) printf("%s\n", buf[ans[i]]); return 0; }