CCF 201812-3 CIDR合并--vector排序+list合并

思路:

如题,用vector存储ip排序,之后再装入list链表中进行插入删除,可避免因大量插入删除而导致的运行超时。

易错点:

之前发布的文章有详细说明,还有一些自己编写的例子,有需要的可以查阅使用。
链接:
https://blog.csdn.net/qq_26873647/article/details/104188744.
关于stl标准模板库中的list容器具体函数功能和使用可以参考:
链接:
http://www.cplusplus.com/reference/.

#include<bits/stdc++.h>
using namespace std;

struct node{
	int ip[4];
	int len;
};
vector<node> vip;
list<node> lip;

//比较函数 
bool cmp(node a,node b){ 
	for(int i=0;i<4;i++){
		if(a.ip[i]!=b.ip[i])return a.ip[i]<b.ip[i];
	}
	return a.len<b.len;
}

//从小到大合并
bool compare(node a,node b){
	int piror=8-a.len%8;
	int range=pow(2,piror)-1;
	int t=a.len/8;
	for(int i=0;i<t;i++){
		if(a.ip[i]!=b.ip[i])return false;
	}
	if(b.ip[t]<=a.ip[t]+range){
		return true;
	}
	return false;
}

//同级合并--已完善 
bool combine(node a,node b,node &neo){         //合并函数
	if(a.len!=b.len)return false;
	neo.len=a.len-1;
	for(int i=0;i<4;i++){
		neo.ip[i]=a.ip[i];
	}
	if(compare(neo,a)&&compare(neo,b)){ //即将要合并的ip是否是合成ip的子集 
		int piror=8-neo.len%8;
     	int range=pow(2,piror)/2;
     	int t=neo.len/8;
     	int m=pow(2,piror);
     	if(neo.ip[t]%m!=0)return false ;//判断neo是否合法 
     	for(int i=0;i<t;i++){
     		if(a.ip[i]!=b.ip[i])return false;
	    }
    	if(b.ip[t]==a.ip[t]+range){
    		return true;
    	}
    	return false;
	}
}

void table(string str){                //制表
    node temp;
	int p=str.find('/'),i=0;
	temp.len=stoi(str.substr(p+1));
	str=str.substr(0,p);
	while((p=str.find('.'))!=-1){
		str[p]=' ';
	}
	stringstream ss;
	string s;
	ss<<str;
	while(ss>>s){
		temp.ip[i++]=stoi(s);
	}
	vip.push_back(temp);
}

void standard(string &str){            //IP标准化 
	int t=3,flag=1,p;
	for(int i=0;i<str.size();i++){
		if(str[i]=='.')t--;
		if(str[i]=='/')flag=0;
	}
	if(flag){
		int len=(4-t)*8;
		str=str+"/"+to_string(len);
	}
	p=str.find('/');
	while(t--){
		str.insert(p,".0");
	}
}

int main(){
	ios::sync_with_stdio(false);
	//输入 
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		string str;
		cin>>str;
		//标准化
		standard(str);
		//制表
		table(str); 
	}
	//排序
	sort(vip.begin(),vip.end(),cmp);
	for(auto it:vip){
		lip.push_back(it);
	}
	
	//从小到大合并
	list<node>::iterator cur,next;
	for(cur=lip.begin();cur!=lip.end();){
		if(++cur==lip.end())break;
		next=cur--;
		if(compare(*cur,*next)){
			lip.erase(next);
		}
		else cur++;
	}
	
	//同级合并--已完善 
	for(cur=lip.begin();cur!=lip.end();){
		next=cur;
		next++;
		if(next==lip.end())break;
		node neo;
		if(combine(*cur,*next,neo)){
			next++;
			cur=lip.erase(cur,next);
		    lip.insert(cur,neo);
		    cur--;
			if(cur!=lip.begin())cur--;
		}
		else cur++;
	} 

	//输出
	for(auto it:lip){
		for(int i=0;i<4;i++){
			cout<<it.ip[i];
			if(i<3)cout<<'.';
		}
		cout<<'/'<<it.len<<endl;
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值