ccf认证 201812-3 CIDR合并(模拟)

题目:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:先定义一个结构体用于存储ip前缀,然后按照题以模拟即可,有一个问题就是n最大是1e5,vector的erase是O(n)的,所以合并操作复杂度是O(nn),可能会超时,我的代码中第一步合并是
o(n)的,但是第二步是o(n
n)的,可以改用list。

代码:
用vector的代码(100分)

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;

struct node {
	int ip[4] , len , ip4[33];
	unsigned int d;
	node(string s) {
		bool flag = 0;
		int cnt = 0;
		d = len = 0; 
		memset(ip,0,sizeof(ip));
		for(int i = 0 ; i < s.length() ; i++) {
			if(s[i] == '.')continue;
			else if(s[i] == '/')  {
				flag = 1;continue;
			}
			else {
				int t = 0;
				while(isdigit(s[i])) {
					t = t * 10 + s[i] - '0';
					i++;						
				}
				i--;
				if(!flag)ip[cnt++] = t;
				else len = t;
			}
		}
		if(!len)len = cnt * 8;
		cnt = 7;
		for(int i = 0 ; i < 4 ; i++) {
			d = d * 256 + ip[i];
			int t = ip[i];
			for(int j = cnt ; j >= cnt - 7 ; j--) {
				ip4[j] = t % 2;
				t /= 2;
			}
			cnt += 8;
		}
	} 
	node(){}
	bool operator < (const node b) const {
		return d < b.d || (d == b.d && len < b.len);
	}
}; 

node a[maxn];
vector<node> ans;
bool vis[maxn];

bool judge(node b , node c) {
	if(c.len < b.len)return false;
	for(int i = 0 ; i < b.len ; i++) {
		if(b.ip4[i] != c.ip4[i]) {
			return false;	
		}
	}
	return true;
}

bool judge1(node b , node c) {
	if(c.len != b.len || c.len == 0)return false;
	for(int i = 0 ; i < b.len - 1 ; i++) {
		if(b.ip4[i] != c.ip4[i])return false;
	}
	int len = b.len - 1;
	if(b.ip4[len] != c.ip4[len]) return true;
	else return false;
}	

int main() {
	int n;
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0 ; i < n ; i++) {
		string s;
		cin >> s;
		a[i] = node(s);
	} 
	sort(a , a + n);
	for(int i = 0 ; i < n ; ) {
		int p = i;
		i++;
		while(i < n && !vis[i]) {
			if(judge(a[p] , a[i])) {
				vis[i] = 1;
				//cout << i << endl;
				i++;
			}
			else break;
		}
	}
	for(int i = 0 ; i < n ; i++) {
		if(!vis[i])ans.push_back(a[i]);
	}
	for(int i = 0 ; i < ans.size() - 1 ; i++) {
		while(i < ans.size() - 1) {
			if(judge1(ans[i] , ans[i + 1])) {
				ans[i].len = ans[i].len - 1;
				ans.erase(ans.begin() + i + 1);
				if(i > 0)i--;
			}
			else break;
		}
	}
	for(int i = 0 ; i < ans.size() ; i++) {
		cout << ans[i].ip[0] << "."<<ans[i].ip[1] << "." << ans[i].ip[2] << "." << ans[i].ip[3] << "/" << ans[i].len<< "\n"; 
	}
	return 0;
}

用list的代码(100分)

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;

struct node {
	int ip[4] , len , ip4[33];
	unsigned int d;
	node(string s) {
		bool flag = 0;
		int cnt = 0;
		d = len = 0; 
		memset(ip,0,sizeof(ip));
		for(int i = 0 ; i < s.length() ; i++) {
			if(s[i] == '.')continue;
			else if(s[i] == '/')  {
				flag = 1;continue;
			}
			else {
				int t = 0;
				while(isdigit(s[i])) {
					t = t * 10 + s[i] - '0';
					i++;						
				}
				i--;
				if(!flag)ip[cnt++] = t;
				else len = t;
			}
		}
		if(!len)len = cnt * 8;
		cnt = 7;
		for(int i = 0 ; i < 4 ; i++) {
			d = d * 256 + ip[i];
			int t = ip[i];
			for(int j = cnt ; j >= cnt - 7 ; j--) {
				ip4[j] = t % 2;
				t /= 2;
			}
			cnt += 8;
		}
	} 
	node(){}
	bool operator < (const node b) const {
		return d < b.d || (d == b.d && len < b.len);
	}
}; 

node a[maxn];
list<node> ans;
bool vis[maxn];

bool judge(node b , node c) {
	if(c.len < b.len)return false;
	for(int i = 0 ; i < b.len ; i++) {
		if(b.ip4[i] != c.ip4[i]) {
			return false;	
		}
	}
	return true;
}

bool judge1(node b , node c) {
	if(c.len != b.len || c.len == 0)return false;
	for(int i = 0 ; i < b.len - 1 ; i++) {
		if(b.ip4[i] != c.ip4[i])return false;
	}
	int len = b.len - 1;
	if(b.ip4[len] != c.ip4[len]) return true;
	else return false;
}	

int main() {
	int n;
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin >> n;
	for(int i = 0 ; i < n ; i++) {
		string s;
		cin >> s;
		a[i] = node(s);
	} 
	sort(a , a + n);
	for(int i = 0 ; i < n ; ) {
		int p = i;
		i++;
		while(i < n && !vis[i]) {
			if(judge(a[p] , a[i])) {
				vis[i] = 1;
				i++;
			}
			else break;
		}
	}
	for(int i = 0 ; i < n ; i++) {
		if(!vis[i])ans.push_back(a[i]);
	}
	for(auto t = ans.begin() ; t != ans.end() ; t++) {
		auto t1 = t;
		t1++;
		while(t1 != ans.end() ) {	
			if(judge1(*t , *t1)) {
				t -> len = t -> len - 1;
				ans.erase(t1);
				if(t != ans.begin())t--;
				t1 = t; t1++;
			}
			else break;
		}
	}
	for(auto t = ans.begin() ; t != ans.end() ; t++) {
		cout << t -> ip[0] << "."<< t -> ip[1] << "." << t -> ip[2] << "." << t -> ip[3] << "/" << t -> len<< "\n"; 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值