CSP 201812-3 CIDR合并

题目链接:http://118.190.20.162/view.page?gpid=T82

 

题目大意:大模拟题意太长了自己读题。。

 

题目思路:首先对字符串操作肯定是麻烦的,提示中第一个叫我们先根据IP排序,再根据前缀长度排序,而题目中又说明了IP是一个整数,那么我们很容易想到,需要将字符串转换成一个整数。而字符串转换的方法也很容易看出来可以是256进制的一种特殊数字,然后我们就可以根据有/就直接得到长度,如果没有就根据.的数量得到,对于IP对应的整数,则根据相关规则也可以得到。然后根据题目要求排序,这样就获得了60分。接下来根据相邻两部分,说如果后面一个是前一个的子集。根据题目的描述很容易看出,一个IP前缀所代表的就是前缀长度对应的字符串后面随便跟数字都是他的子集,那么就是后面的在前面的有效长度范围内都相等,从而我们可以想到位运算。最后一个操作的方法跟第二个很相似,就是我们需要注意,a和b的并集是a',所以他们的长度必须是相等的,否则就不可能并集是a',同时要求他们前len-1个数字要相同,最后一个要不同,这样才能够并集出a',最后根据256进制转换就行。

 

以下是代码:

#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int MAXN = 1e5+5;
char s[20];
struct node{
    ll val,len;
}a[MAXN];
ll pre[5],p[MAXN];
int vis[MAXN];
bool cmp(node a,node b){
    if(a.val==b.val)return a.len=31-len+1;i--){
                ll temp=1ll<31-len+1;i--){
                ll temp=1ll<31-len+1;i--){
                    ll temp=1ll<=1&&vis[pos])pos--;
                if(pos>=1){
                    r=l;
                    l=pos;
                }
                else{
                    while(vis[r]&&r<=n)r++;
                }
            }
            else{
                l=r;
                r++;
                while(vis[r]&&r<=n)r++;
            }
        }
        for(int i=1;i<=n;i++){
            if(vis[i])continue;
            int num=0;
            ll temp=a[i].val;
            for(int j=1;j<=4;j++)p[j]=0;
            while(temp){
                p[++num]=temp%256;
                temp/=256;
            }
            for(int j=4;j>=1;j--){
                printf("%lld%c",p[j],j==1?'/':'.');
            }
            printf("%lld\n",a[i].len);
        }
    }
    return 0;
}

 

你可能感兴趣的:(模拟)