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\n", 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] != '\0'; 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] == '\0')
{
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] == '\0')
{
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;
}
CCF-CSP题解 201812-3 CIDR合并的更多相关文章
- CCF 201812-3 CIDR合并
CCF 201812-3 CIDR合并 //100分 93ms #include<stdio.h>//CCF上stdio.h比cstdio快!!! #include<string.h ...
- CCF CSP 201604-2 俄罗斯方块
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201604-2 俄罗斯方块 问题描述 俄罗斯方块是俄罗斯人阿列克谢·帕基特诺夫发明的一款休闲游 ...
- CCF CSP 201703-3 Markdown
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-3 Markdown 问题描述 Markdown 是一种很流行的轻量级标记语言(l ...
- CCF CSP 201312-3 最大的矩形
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201312-3 最大的矩形 问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i( ...
- CCF CSP 201609-3 炉石传说
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201609-3 炉石传说 问题描述 <炉石传说:魔兽英雄传>(Hearthston ...
- CCF CSP 201403-3 命令行选项
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-3 命令行选项 问题描述 请你写一个命令行分析程序,用以分析给定的命令行里包含哪些 ...
- CCF CSP 201709-4 通信网络
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201709-4 通信网络 问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M ...
- CCF CSP 201409-3 字符串匹配
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201409-3 字符串匹配 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那 ...
- CCF CSP 201503-3 节日
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201503-3 节日 问题描述 有一类节日的日期并不是固定的,而是以“a月的第b个星期c”的形 ...
- CCF CSP 201509-2 日期计算
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201509-2 日期计算 问题描述 给定一个年份y和一个整数d,问这一年的第d天是几月几日? ...
随机推荐
- 你真的会用JavaScript中的sort方法吗
在平时的业务开发中,数组(Array) 是我们经常用到的数据类型,那么对数组的排序也很常见,除去使用循环遍历数组的方法来排列数据,使用JS数组中原生的方法 sort 来排列(没错,比较崇尚JS原生 ...
- 2C 还是 2B,跟找工作有什么关系?
通常,我们会把公司的业务类型分成以下几种: 2C,to Customer,指面向个人客户的业务,即将公司的产品或服务销售给个人,通常做出购买决策的个人也是使用产品或服务的用户.举例说明,像 BAT 发 ...
- python:Asyncio模块处理“事件循环”中的异步进程和并发执行任务
python模块Asynico提供了管理事件.携程.任务和线程的功能已经编写并发代码的同步原语. 组成模块: 事件循,Asyncio 每个进程都有一个事件循环. 协程,子例程概念的泛化,可以暂停任务, ...
- 生产者-消费者模型在Hudi中的应用
介绍 生产者-消费者模型用于解耦生产者与消费者,平衡两者之间的能力不平衡,该模型广泛应用于各个系统中,Hudi也使用了该模型控制对记录的处理,即记录会被生产者生产至队列中,然后由消费者从队列中消费,更 ...
- MySQL常用的查询语句回顾
让你快速复习语句的笔记宝典. create table users( username varchar(20) primary key, userpwd varchar(20) ) alt ...
- TypeError: Cannot read property '_t' of undefined (VUE + ElementUI + i18n)
在使用vue的ElementUI库,在多语言时报错: TypeError: Cannot read property '_t' of undefined 错误是在点菜单栏时随机抛出的,F12抓不到,只 ...
- 【Luogu P1090】合并果子
Luogu P1090 [解题思路] 刚看到这题的时候,第一反应就是每次取两个最小,然后重新排序,再取最小.但是这样会TLE. 既然找最小的,那就可以利用单调队列了.显然输入的数据是不具有单调性的,但 ...
- 12、pytest -- 缓存:记录执行的状态
目录 1. cacheprovider插件 1.1. --lf, --last-failed:只执行上一轮失败的用例 1.2. --ff, --failed-first:先执行上一轮失败的用例,再执行 ...
- firebug和HTML查看源代码的区别
1.审查元素或者开发者工具或firebug看到的html是现在实时性的内容,经过js修改的: 2.而网页查看源代码看到的是最开始浏览器收到的HTTP响应,静态的html.
- Java基础面试题及答案(六)
异常 74. throw 和 throws 的区别? throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理.而throw则是 ...