列表

详情


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路由个数
第1行:表示路由个数k
第2~k+1行: 表示一个CIDR路由, 形如 x.x.x.x/x

输出描述

n+1行, n表示去重后剩下的CIDR路由个数
第1行:n
第2~n+1行: 表示一个去重后的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;
}


上一题