ccf csp 201812-3 CIDR合并 C++ 90分

题目
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
样例输入

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分暂时没找到在哪,有大神可提供思路的请留言,感激不尽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值