题目
样例输入
2
1
2
样例输出
1.0.0.0/8
2.0.0.0/8
样例输入
2
10/9
10.128/9
样例输出
10.0.0.0/8
样例输入
2
0/1
128/1
样例输出
0.0.0.0/0
解题思路
思路按照官方思路就行了,我主要讲一下实现方式
使用结构体,并重载<符号,用set来维护整个ip列表,可以自动排序,并且以 O(logN)的复杂度 快速删除,插入元素。
如果使用vector数组,删除插入一个元素的复杂度为 0(N),则总复杂度为O(N方),对于 n为1e5的数据大小肯定超时。
第零步:处理输入
步骤1:判断是否有/
,有的话则后面数字为前缀长度,否则通过前面的前缀判断前缀长度。
步骤2:处理前缀,用一个int 数组 int staIp[4];
存前缀。(这样利于结果输出).
步骤3:将staIp[4]数组中四个值,按256进制转换成一个整数,存为long long ip;
(用于排序和判断是否合并)
第一步:排序
步骤:直接插入set即可,会自动排序。
备注:这题样例挺奇怪的,光写排序的话就有60分。
第二步:从小到大合并
步骤:从头遍历set的相邻元素,判断后一个是否是前一个的子集,是则删除后一个。
判断方法:从计网的判断原理归纳来看就是,若ip2是ip1的子集,则有两个条件:
1.ip1.len < ip2.len。
2.ip2的前ip1.len
个二进制数与ip1的前ip1.len
个二进制数相同。
这时候,直接使用按位异或操作即可,若ip2是ip1的子集,则异或结果的前ip1.len
个二进制数必定是0,即异或结果小于pow(2,32-ip1.len)
,可直接用此结论判断
关键代码如下:
【注】迭代器只能用 自增自减运算符,这样写是不对的 auto j = i+1 ;
,只能写成i++;auto j = i;i--;
if(node1.len<node2.len )
{
long long t1 = node1.ip^node2.ip;
if( t1<pow(2,32-node1.len) ) return true;
}
return false;
第三步:合并同级
步骤:和第二步步骤类似,不同在于合并的判定条件。
从题中易得,若ip1和ip2可以合并,则有:
1.ip1.len == ip2.len
2.ip1和ip2的前 ip1.len-1
个二进制数字相同,第ip1.len
二进制数字个不同.
又因为此时ip是按ip大小排序的,所以ip1 的第ip1.len
个数字肯定是0,ip2的第ip1.len
个数字肯定是1,ip1和ip2之后的32-ip1.len
个数字全0(ip合法的定义).所以ip1和ip2的按位异或结果,除了第ip1.len
个数字是1,其他全0.由此解论可以判定同级合并
关键代码如下:
if( node1.len == node2.len && node1.len>0)
{
long long t1 = node1.ip^node2.ip;
if(t1 == pow(2,32-node1.len)) return true;
}
return false;
代码总和:
命名不太规范,还请见谅。
#include <bits/stdc++.h>
using namespace std;
struct Node
{
long long ip;
int len;
int staIp[4]; //存标准形式
bool operator<(const Node& b)const //重载,用于排序
{
return ip == b.ip?len<b.len:ip<b.ip;
}
Node(int i,int l,int s[])
{
ip = i; len = l;
for(int j=0;j<4;j++)
{
staIp[i] = s[i];
}
}
Node(string a)
{
int pos = a.find('/');
if( pos != string::npos ) //标准型和省略前缀型
{
int temp=0;
for(int i= pos+1;i<a.size();i++ )
{
temp = temp*10;
temp += a[i]-'0';
}
len =temp;
vector<int> t1;
int start = 0;
for(int i=1;i<pos;i++)
{
if( a[i] =='.' )
{
int temp1 = stoi( a.substr(start,i-start) );
//cout<<a.substr(start,i-start)<<' '<<temp1<<endl;
t1.push_back( temp1 );
start = i+1;
}
}
int temp1 = stoi( a.substr(start,pos-start) );
t1.push_back( temp1 );
//cout<<a.substr(start,pos-start)<<' '<<temp1<<endl;
long long tip=0;
for(int i=0;i<4;i++ )
{
tip = tip*256;
if( i<t1.size() )
{
staIp[i] = t1[i];
tip+= t1[i];
//cout<<staIp[i]<<endl;
}
else
{
staIp[i] = 0;
//cout<<0<<endl;
}
}
ip = tip;
}
else //省略长度型
{
vector<int> t1;
int start = 0;
int len1 = 0;
for(int i=1;i<a.size();i++)
{
if( a[i] =='.' )
{
int temp1 = stoi( a.substr(start,i-start) );
t1.push_back( temp1 );
//cout<<a.substr(start,i-start)<<' '<<temp1<<endl;
start = i+1;
len1 +=8;
}
}
int temp1 = stoi( a.substr(start,a.size()-start) );
t1.push_back( temp1 );
//cout<<a.substr(start,pos-start)<<' '<<temp1<<endl;
len1 += 8;
len = len1;
long long tip=0;
for(int i=0;i<4;i++ )
{
tip = tip*256;
if( i<t1.size() )
{
staIp[i] = t1[i];
tip+= t1[i];
//cout<<staIp[i]<<endl;
}
else
{
staIp[i] = 0;
//cout<<0<<endl;
}
}
ip = tip;
}
}
};
bool hebing1(Node node1,Node node2)
{
if(node1.len<node2.len )
{
long long t1 = node1.ip^node2.ip;
if( t1<pow(2,32-node1.len) ) return true;
}
return false;
}
bool hebing2(Node node1,Node node2)
{
if( node1.len == node2.len && node1.len>0)
{
long long t1 = node1.ip^node2.ip;
if(t1 == pow(2,32-node1.len)) return true;
}
return false;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); //加速cin和cout,可有可无
int n;
cin>>n;
set<Node> setips ;
string s;
while(n--)
{
cin>>s;
Node node(s);
setips.insert(node);
}
for(auto i = setips.begin();i!=setips.end();i++) //小到大合并
{
i++;
auto j = i;
i--;
if( j!=setips.end() )
{
Node node1 = *i;
Node node2 = *j;
if( hebing1(node1,node2) )
{
setips.erase(j);
i--;
}
}
}
int flag1 = 0;
for(auto i = setips.begin();i!=setips.end();i++) //同级别合并
{
i++;
auto j = i;
i--;
if( j!=setips.end() )
{
Node node1 = *i;
Node node2 = *j;
if( hebing2(node1,node2) )
{
setips.erase(j);
auto k =i;
node1.len--;
i--;
setips.erase(k);
setips.insert(node1);
}
}
}
for(auto i =setips.begin();i!=setips.end();i++ )
{
Node node = *i ;
for(int j=0;j<4;j++)
{
cout<<node.staIp[j];
if( j != 3) cout<<'.' ;
}
cout<<'/'<<node.len<<endl;
// cout<<'/'<<node.len<<"|"<<setw(8)<<setfill('0')<<hex<<node.ip ;
// cout<<dec<<endl;
}
return 0;
}
得了90分,剩下10分暂时没找到在哪,有大神可提供思路的请留言,感激不尽。