201812 CSP认证 | CIDR合并

CIDR合并
难是真的不难但是也写了我几个小时服了
这道题在有计网的基础上就很好理解了,没有在格式上有任何刁难你的。这里不讲背景了
官网提交结果以及满分代码如下:
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<string, int> PSI;
const int N = 1e5 + 10;
int n;
struct node{
    string ip;
    int len;
    ll ten;  //ip前缀的十进制表示:为了方便排序
};
vector<node> ipPool;
vector<node> merge1; //第一轮合并的结果
vector<node> res;   //同级合并的最终结果
int to_int(string str)
{
    stringstream ssin(str);
    int x;
    ssin >> x;
    return x;
}
string to_str(int m)
{
    stringstream ssin;
    ssin << m;
    string str;
    ssin >> str;
    return str;
}
//用于第一步排序
bool cmp(node x, node y)
{
    if(x.ten == y.ten) return x.len < y.len;
    else return x.ten < y.ten;
}
//处理一个输入的ip,将其处理后存储到ipPool中
void handle(string str)
{
    int k = str.find('/');
    int len = 0; node temp;
    if(k != -1)  { len = to_int(str.substr(k + 1)); str = str.substr(0, k); }

    //开始解析ip, 将字符串按照'.'分割开来
    vector<string> vec;
    for(int i = 0, j = 0; i < str.size(); i = j + 1){  //将str用'+'分割开来
        j = str.find('.', i);  //从下标i开始找+号
        if(j == -1) j = str.size();
        vec.push_back(str.substr(i, j - i));
    }
    if(!len) len = vec.size() * 8;  //省略了长度型的ip书写方式

    if(vec.size() != 4){
        int sz = vec.size();
        for(int i = 1;i <= 4 - sz;i ++){
            vec.push_back("0");  //补0
        }
    }
    string ip = ""; ll ten = 0;  //将ip转化为十进制的数字
    for(int i = 0;i < vec.size();i ++) {
        ip = ip + vec[i] + '.';
        ll x = to_int(vec[i]);
        x <<= ((3 - i) * 8);
        ten += x;
    }

    ip = ip.substr(0, ip.size() - 1); //删去最后一个点
    ip += "/" + to_str(len);

    temp.ip = ip; temp.len = len; temp.ten = ten;
    ipPool.push_back(temp);
}

//判断ipPool中b位置ip的匹配集是否是a位置ip匹配集的子集
bool subset(int a, int b)
{
    int lena = ipPool[a].len, lenb = ipPool[b].len;
    if(lena > lenb) return false;

    //接下来是lena <= lenb的情况,也就是二者的前lena个bit位置必须相同
    int delta = 32 - lena;
    int tena = ipPool[a].ten >> delta, tenb = ipPool[b].ten >> delta;  //只保留前lena位

    int temp = tena ^ tenb;
    if(temp) return false;  //前lena个bit位不相同
    return true;
}
//将ipPool中的元素从小到大进行合并
void small_Large_Merge()
{
    int a = 0, b = 1;
    bool st[N]; //考虑某个位置的元素是否存在
    memset(st, true, sizeof st);
    while(b < n){    //n也是ipPool的大小
        if(subset(a, b)){ st[b] = false; b ++; }
        else{ a = b; b ++; }
    }

    for(int i = 0;i < n;i ++){
        if(st[i]) merge1.push_back(ipPool[i]);
    }
}
//对merge1进行同级合并
void final_Merge()
{
    int a = 0, b = 1, sz = merge1.size();
    bool st[N];
    memset(st, true, sizeof st);  //功能同前面相同
    while(b < sz){
        node t;  //存储中间结果
        int lena = merge1[a].len, lenb = merge1[b].len;
        bool flag = false;  //是否能合并
        if(lena == lenb){
            //看二者是否能合并, 也就是看前len - 1位置是否完全相同,且最后一位不同
            int delta = 32 - lena;
            int tena = merge1[a].ten >> delta, tenb = merge1[b].ten >> delta;
            int tena2 = merge1[a].ten >> (delta + 1), tenb2 = merge1[b].ten >> (delta + 1);
            int cnt = 0;   //用来记录前len位有几位不相同
            int temp = tena ^ tenb;
            while(temp){
                cnt ++;
                temp &= (temp - 1);
            }

            temp = tena2 ^ tenb2;
            if(!temp && cnt == 1){  //前len - 1相同,第len不同,可以合并
                flag = true;
                t.ten = merge1[a].ten;
                t.len = merge1[a].len - 1; //长度不同
                string ip = merge1[a].ip;
                int k = ip.find('/');
                ip = ip.substr(0, k + 1);
                ip += to_str(t.len);
                t.ip = ip;
            }
        }
        if(flag){
            merge1[a] = t; st[b] = false;  //更新; a向前回溯
            if(a > 0){   //a > 0才有回溯的必要,注意这里st[0]是不可能为false的
                b = a; a --;
                while(!st[a]) a --;
            }
            else { //无需向前找了
                while(b < sz && !st[b]) b ++;
            };
        }
        else {
            a = b;
            b ++;
            while(b < sz && !st[b]) b ++;
        }
    }
    for(int i = 0;i < sz;i ++){
        if(st[i]) res.push_back(merge1[i]);
    }
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);

    cin >> n;
    for(int i = 0;i < n;i ++){
        string ip; cin >> ip;
        handle(ip);
    }
    sort(ipPool.begin(),ipPool.end(), cmp);

    //现在开始从小到大合并
    small_Large_Merge();
    //同级合并
    final_Merge();
    for(auto x : res){
        cout << x.ip << endl;
    }

    return 0;
}

本题我用了位运算来实现。能否合并的关键就是看前几位是否是相同的,如果前x位相同,第x + 1的异或结果为1的话,此时两个就可以合并成一个。因此我设置了一个len来保存ip地址的十进制数。
但就是这个我改了很久的错误
第62行我的初始代码是:ten += ( x << ((3 - i) * 8) ),结果总是负数
后来又测试了几个如下:
在这里插入图片描述
其实就是符号的问题。
如果我直接对128移位置,只在低位补零;此时的x的表示形式就是10000000 0000000 0000000 0000000。从补码的角度来说,因为最高位为1,此时就是负数!!!
而我若先赋值为128,此时这个数据只是存在与x空间的存储形式为00000000 00000000 00000000 10000000,再移位;此时变为00000000 10000000 0000000 0000000 0000000最高位仍然为0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/490672.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发实例:【demo-搜索历史记录】

图片演示效果&#xff1a; 鸿蒙OS开发更多内容↓点击HarmonyOS与OpenHarmony技术鸿蒙技术文档开发知识更新库gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md在这。或mau123789学习&#xff0c;是v喔 代码演示&#xff1a; // 注&#xff1a;当前代码基于宽度为…

【Leetcode】top 100 二叉树

基础知识补充 完全二叉树&#xff1a;顺序存储&#xff08;数组&#xff09; 非根节点的父节点序号floor((i-1)/2) 序号i的左孩子节点序号2*i1 右孩子节点序号2*i2 一般二叉树&#xff1a;链式存储 结构&#xff1a;left指针指向左子节点&#xff0c;right指针指向右子节点&am…

vue3+threejs新手从零开发卡牌游戏(十五):创建对方场地和对方卡组

首先创建对方场地&#xff0c;game/site/p2.vue和p1.vue代码一样&#xff0c;注意把里面的命名“己方”修改成“对方”&#xff0c;game/site/index.vue代码如下&#xff0c;用rotateZ翻转一下即可得到镜像的对方场地&#xff1a; // 添加战域plane const addSitePlane () >…

Leetcode 76 最小覆盖子串 java版

官网链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 1. 问题&#xff1a; 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 "" 。 注意&#xff1a; 对于 …

【项目管理——时间管理】【自用笔记】

1 项目时间管理&#xff08;进度管理&#xff09;概述 过程&#xff1a;&#xff08;2—6&#xff09;为规划过程组&#xff0c;7为监控过程组 题目定义&#xff1a;项目时间管理又称为进度管理&#xff0c;是指确保项目按时完成所需的过程。目标&#xff1a;时间管理的主要目标…

FlyControls 是 THREE.js 中用于实现飞行控制的类,它用于控制摄像机在三维空间中的飞行。

demo演示地址 FlyControls 是 THREE.js 中用于实现飞行控制的类&#xff0c;它用于控制摄像机在三维空间中的飞行。 入参&#xff1a; object&#xff1a;摄像机对象&#xff0c;即要控制的摄像机。domElement&#xff1a;用于接收用户输入事件的 HTML 元素&#xff0c;通常…

蓝桥杯刷题8

1. 世纪末的星期 import java.util.Calendar; public class Main {public static void main(String[] args) {Calendar calendar Calendar.getInstance();for(int year 1999;year<100000;year100){calendar.set(Calendar.YEAR,year);calendar.set(Calendar.MONTH,11);cale…

力扣hot100:207. 课程表

这是一道拓扑排序问题&#xff0c;也可以使用DFS判断图中是否存在环。详情请见&#xff1a;官方的BFS算法请忽略&#xff0c;BFS将问题的实际意义给模糊了&#xff0c;不如用普通拓扑排序思想。 数据结构&#xff1a;图的拓扑排序与关键路径 拓扑排序&#xff1a; class Sol…

手撕算法-三数之和

描述 分析 排序双指针直接看代码。 代码 public static List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);List<List<Integer>> res new ArrayList<>();for(int k 0; k < nums.length - 2; k){if(nums[k] > 0) break; …

通讯录管理系统实现(C++版本)

1.菜单栏的设置 &#xff08;1&#xff09;我么自定义了一个showmenu函数&#xff0c;用来打印输出我们的菜单栏&#xff1b; &#xff08;2&#xff09;菜单栏里面设置一些我们的通讯录里面需要用到的功能&#xff0c;例如增加联系人&#xff0c;删除联系人等等 2.退出功能…

【Python系列】Python 中 YAML 文件与字典合并的实用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

MySQL数据库------------探索高级SQL查询语句

目录 一、常用查询 1.1按关键字排序 1.2简单的select条件查询(where) 二、排序 2.1升序排列 2.2降序排序 三、order by 查询结果排序 ①order by还可以结合where进行条件过滤&#xff0c;筛选地址是哪里的学生按分数降序排列 ②查询学生信息先按hobbyid降序排列&#…

面试官问我 ,try catch 应该在 for 循环里面还是外面?

首先 &#xff0c; 话说在前头&#xff0c; 没有什么 在里面 好 和在外面好 或者 不好的 一说。 本篇文章内容&#xff1a; 使用场景 性能分析 个人看法 1. 使用场景 为什么要把 使用场景 摆在第一个 &#xff1f; 因为本身try catch 放在 for循环 外面 和里面 &#…

(一)whatsapp 语音通话基本流程

经过了一整年的开发测试&#xff0c;终于将whatsapp 语音通话完成&#xff0c;期间主要参考webrtc的源码来实现.下面简要说一下大致的步骤 XMPP 协商 发起或者接受语音通话第一步是发起XMPP 协商&#xff0c;这个协商过程非常重要。下面是协商一个包 <call toxxxs.whatsap…

2024 年广西职业院校技能大赛高职组《云计算应用》赛项赛题第 4 套

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&…

背包DP模板

01背包 01背包-1 #include <bits/stdc.h> using namespace std;const int N 1e5 10; int n, m, f[N][N], v[N], w[N];int main() {cin >> n >> m;for (int i 1; i < n; i) {cin >> v[i] >> w[i];}for (int i 1; i < n; i) {for (int…

构建多语言数字资产交易平台和秒合约系统:从概念到实现

多语言交易所开发定制秒合约平台币数字所网站制作一条龙搭建 第一步&#xff1a;需求分析 在开始搭建多语言交易所和秒合约平台之前&#xff0c;需要进行详细的需求分析&#xff0c;包括以下几个方面&#xff1a; 功能需求&#xff1a;确定交易所需要提供的功能&#xff0c;包…

要创建企业百度百科,需要注意以下技巧和原则。

&#xfffd;&#xfffd;&#xfffd;词条内容技巧 词条排版必须美观&#xff0c;内容分段&#xff0c;然后制作副标题。例如&#xff0c;一个企业的名称分为小标题&#xff0c;如企业介绍、企业文化、企业发展、企业历史和企业新闻。这不仅可以给读者一个良好的阅读&#xf…

Learn OpenGL 30 SSAO

SSAO 我们已经在前面的基础教程中简单介绍到了这部分内容&#xff1a;环境光照(Ambient Lighting)。环境光照是我们加入场景总体光照中的一个固定光照常量&#xff0c;它被用来模拟光的散射(Scattering)。在现实中&#xff0c;光线会以任意方向散射&#xff0c;它的强度是会一…

python 第一次作业

因为笔者有一些 c/c 语言的基础&#xff0c;所以应该学 python 会稍微简单一些 格式化输出的时候&#xff0c;保留2位小数的格式是 # 假设输出 a &#xff0c;并且 a 保留 2 位小数 print(%.2f%a)输入 输入的时候所有的输入都是字符串类型&#xff0c;我们需要进行类型转换 …