zoukankan      html  css  js  c++  java
  • CCF-CSP题解 201812-3 CIDR合并

    题目想求与给定前缀列表等价的包含IP前缀数目最少的前缀列表。

    首先是怎么存储前缀列表。用一个long long存储IP地址,再存一个前缀长度,封装在一个结构体里(<ipNum, len>),方便后面排序等操作。IP前缀有三种输入格式,稍微分情况讨论一下。

    接着以(ipNum)为第一关键字,(len)为第二关键字升序排序。

    然后考虑去除匹配集被其它IP前缀包含的IP前缀。考虑之前匹配集范围的上届(mmax),顺序遍历一下就好了。将剩余的IP列表按之前顺序存在一个静态链表中。

    最后将相邻的可合并的IP前缀合并,其实就是前缀长度最后一位0和1,之前完全相同即可。

    温习一下链表的插入删除操作。

    #include <bits/stdc++.h>
    typedef long long LL;
    const int maxn = 1000000;
    
    using namespace std;
    
    struct tIP
    {
        LL ipNum;
        int len;
        int before, next;
        tIP()
        {
            before = next = -1;
        }
        bool operator < (const tIP &y) const
        {
            if(ipNum == y.ipNum)
                return len < y.len;
            return ipNum < y.ipNum;
        }
        void show()
        {
            LL num[5];
            LL temp = ipNum;
            for (int i = 4; i >= 1; i--)
            {
                num[i] = temp % 256;
                temp /= 256;
            }
            for (int i = 1; i <=4; i++)
            {
                printf("%lld", num[i]);
                if (i == 4)
                    printf("/");
                else
                    printf(".");
            }
            printf("%d
    ", len);
        }
    };
    tIP ip[maxn+10];
    
    LL getMMax(tIP iip)
    {
        LL temp = (1LL << (32-iip.len)) - 1;
        return iip.ipNum | temp;
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
    
        char s[30];
        for (int id = 1, slash, dotCnt, style; id <= n; id++)
        {
            slash = 0;
            dotCnt = 0;
            scanf("%s", s + 1);
            for (int i = 1; s[i] != ''; i++)
            {
                if (s[i] == '/')
                    slash = 1;
                if (s[i] == '.')
                    dotCnt ++;
            }
    
            if (slash == 1 && dotCnt == 3)
                style = 1;
            else if (slash == 1 && dotCnt < 3)
                style = 2;
            else
                style = 3;
    
            LL num[5];
            memset(num, 0, sizeof(num));
            if (style == 1 || style == 2)
            {
                for (int i = 1, temp = 0, numCnt = 1; ; i++)
                {
                    if (s[i] == '.' || s[i] == '/')
                    {
                        num[numCnt++] = temp * 1LL;
                        temp = 0;
                    }
                    else if (s[i] == '')
                    {
                        ip[id].len = temp;
                        break;
                    }
                    else
                    {
                        temp = temp * 10 + s[i] - '0';
                    }
                }
            }
            else
            {
                for (int i = 1, temp = 0, numCnt = 1; ; i++)
                {
                    if (s[i] == '.')
                    {
                        num[numCnt++] = temp * 1LL;
                        temp = 0;
                    }
                    else if (s[i] == '')
                    {
                        num[numCnt++] = temp * 1LL;
                        ip[id].len = (numCnt-1) * 8;
                        break;
                    }
                    else
                    {
                        temp = temp * 10 + s[i] - '0';
                    }
                }
            }
            LL ans = 0;
            for (int i = 1; i <= 4; i++)
            {
                ans = ans * 256 + num[i];
            }
            ip[id].ipNum = ans;
        }
    
        sort(ip + 1, ip + 1 + n);
    
        LL mmax = -1;
        int st = 0, en = n + 1;
        ip[st].before = -1;
        ip[st].next = en;
        ip[en].before = st;
        ip[en].next = -1;
        for (int id = 1, prev = 0; id <= n; id++)
        {
            if (ip[id].ipNum > mmax)
            {
                ip[id].before = prev;
                ip[id].next = en;
                ip[prev].next = ip[en].before = id;
                prev = id;
                mmax = getMMax(ip[id]);
            }
        }
    
        int pNow = ip[0].next;
        while (pNow != en)
        {
            int p1 = pNow, p2 = ip[pNow].before;
            if (p2 == 0)
                pNow = ip[pNow].next;
            else
            {
                if (ip[p1].len == ip[p2].len &&
                    (ip[p2].ipNum & (1LL << (32-ip[p2].len))) == 0 &&
                    (ip[p2].ipNum | (1LL << (32-ip[p2].len))) == ip[p1].ipNum)
                {
                    ip[p1].before = ip[p2].before;
                    ip[ip[p1].before].next = p1;
                    ip[p1].ipNum = ip[p2].ipNum;
                    ip[p1].len --;
                }
                else
                {
                    pNow = ip[pNow].next;
                }
            }
        }
    
        pNow = ip[0].next;
        while (pNow != en)
        {
            ip[pNow].show();
            pNow = ip[pNow].next;
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    qq
    qqq
    q
    .json文件
    q
    q
    q
    找jar包的网址
    1qq
    day18(JDBC事务&连接池介绍&DBUtils工具介绍&BaseServlet作用)
  • 原文地址:https://www.cnblogs.com/acboyty/p/11363132.html
Copyright © 2011-2022 走看看