[笔记](更新中)CSP-S 2024 查漏补缺

news/2024/11/15 17:34:23/文章来源:https://www.cnblogs.com/Sinktank/p/18377850

复习内容部分来自NOI大纲中入门级和提高级的内容。

联合体(Union)

联合体是一种复合数据类型,其的定义上与结构体的定义类似。

与结构体不同,联合体中的所有元素共用一块内存,所以它占空间大小一般是最大成员的大小(不考虑对齐的情况下),相应地,任意时刻只有一个成员带有值,如果访问其他成员,得到的值可能有损坏。

对于不同的时刻需要使用不同类型的数据,且只使用刚赋值的成员的情况,无需开多种类型的变量,只需要用联合体即可,更节省空间。

union node{int a;char b;double c;short d[5];
}t;
int main(){cout<<sizeof(t)<<"\n";//Output : 16//解释:最大成员是short d[5],占2*5=10字节,//      再对其到double的8字节,即为16t.a=100;t.c=114514.191981;t.d[3]=32767;cout<<t.a<<" "<<t.c<<" "<<t.d[3]<<"\n";//Output : 307931975 nan 32767//解释:因为是共用空间,所以一般最后赋值的位置才不被损坏return 0;
}

原码和补码

我们用原码表示有符号整数,就是把二进制的最高位作为符号位。拿\(8\)位整数举例,\(-2\)的原码是1000 0010\(5\)的原码是0000 0101

然后我们可以发现一些问题:

  • 原码不能直接相加。比如\(-2+5\),按原码计算1000 0010+0000 0101得到10000111,是十进制的\(-7\)
  • 原码的\(0\)有正负之分。这不仅是对空间的浪费,还会引发一系列冲突。

我们之所以要设计数在计算机里的表示法,就是为了能够方便地对它们进行运算。我们不妨先思考一下,什么样的表示法能支持数的相加。

首先我们要相加,那么依照的就是无符号整数相加、自然溢出的逻辑,相应地就不存在符号位的概念。

根据相加的逻辑,我们很容易得出\(0\)应该表示为0000 0000\(1\)应该表示为0000 0001……也就是说,非负数的表示和原码一样。

负数呢?这就可以用自然溢出嘛,\(-1\)就相当于\(+255\)\(-2\)就相当于\(+254\)……所以\(-1\sim -128\)分别表示为1111 1111\(\sim\)1000 0000。同时我们发现,\(\pm 0\)的问题也被解决了。

这种表示法就叫做补码,计算机中有符号整数都是用它来存储的。

和原码对比一下:

虽然说补码不存在符号位,但我们也可以用最高位来判断正负,\(1\)是负数,\(0\)非负。

补码的系统定义:

  • 非负数的补码就是原码。
  • 负数的补码是原码除符号位全部取反,再\(+1\)
  • 特别地,\(-128\)的补码是1000 0000(这里拿\(8\)位整数举例,其他同理)。

理解起来也很简单,\(x<0\)时,\(x\)的补码是\(256+x=255+x+1\),其中“\(255+x\)”,就是把\(x\)的原码除符号位外都取反。

然而\(-128\)没有原码,我们正好发现原来那个\(-0\)给空出来了,人为规定为\(-128\)

一些笔记用“\(127+1=-128\)”作为例子来引入,实际上有符号整数的溢出是未定义行为

#include<bits/stdc++.h>
using namespace std;
int x;
int main(){cin>>x;cout<<x+1<<"\n";if(x+1<x) cout<<"overflow";else cout<<"not overflow";return 0;
}

可以试试上面的代码,如果编译器比较新,或者吸了氧,输入2147483647时,可能输出是-2147483647 not overflow,原因是编译器看到\(x+1<x\),知道只有溢出才可能为真,而溢出是未定义行为,所以直接认定它为假了(以上内容来自洛谷日报#265)。

补码还有一个不错的特性,补码的补码\(=\)原码,能直接从表格观察出来。证明:设\(x<0\),则\(x\)的补码就是\(256+x\),作为原码对应的数是\(-128-x\)(去掉最高位\(128\)再取反),\(x\)的补码是\(-128-x\)的原码,故得证。

哈夫曼编码

对于一个字符串,我们为了便于传输,常常把它编码成一个01串。编码方式有很多种,最简单的就是用每个字符的ASCII码值来编码,这种编码方式叫等长编码,每个字符都用\(8\)位二进制来表示。

虽然操作简单,但传输效率却不高,而哈夫曼编码是变长编码,它可以让出现频率更高的字符,编码长度更短,同时不会出现冲突问题。

举例子,AAAAABBBBCCCDDE中,每种字母出现次数如下表所示:

A B C D E
5 4 3 2 1

我们按出现次数从小到大排序:

E D C B A
1 2 3 4 5

我们把字母看作树上的节点,出现次数作为该点的权值,初始节点之间不相连。然后重复进行下面的操作:

  • 取出森林里权值最大的\(2\)节点,把它们作为一个新节点的左右儿子(顺序无所谓),新节点的权值是两点权值的和。

最后得到一棵树,这就是哈夫曼树:

根据构造过程,非叶子节点一定有\(2\)个子节点。我们用\(0\)\(1\)分别表示连接左孩子的边、连接右孩子的边:

这样每个叶子节点就有一个唯一的二进制表示了,比如D的表示就是001,这就是每个字母的哈夫曼编码。

哈夫曼编码一定是最优编码,因为编码的总位数实际上是\(\sum\limits_{i=1}^{n} cnt[i]\times len[i]\),其中\(cnt[i],len[i]\)分别表示第\(i\)个字母出现次数和编码长度。我们根据贪心的思想,一定把\(len\)最小的放在最下面,最大的放在最上面。

迭代器

迭代器是一种用于遍历容器的指针。

迭代器有\(3\)中类型:前向迭代器,双向迭代器,随机访问迭代器。

  • 前向迭代器:只能单项移动,即p++++p,支持取值,赋值,可以用!===比较位置。
  • 双向迭代器:包含前向迭代器的功能,并支持p----p
  • 随机访问迭代器:包含双向迭代器的功能,并支持直接返回\(p\)的第\(i\)个元素的引用,支持p-=xp+=xp+xp-x,支持用>=<=><比较位置,还可以用两个迭代器相减,得到它们下标的差。

不同容器支持的迭代器类型:

  • 前向迭代器:unordered_map , unordered_multimap , unordered_set , unordered_multiset
  • 双向迭代器:list , set , multiset , map , multimap
  • 随机访问迭代器:vector , deque , array
  • 不支持迭代器:stack , queue

迭代器数据类型的定义:[type]::iterator it;,例如map<string,int>::iterator it;,有时可以直接用auto代替,让编译器自动填充类型。
遍历(用vector举例):

for(auto it=v.begin();it!=v.end();it++)cout<<*it<<" ";

倒序遍历需要把iterator改成reverse_iterator,循环写成:

for(auto it=v.rbegin();it!=v.rend();it++)cout<<*it<<" ";

其中,这四个方法返回位置的关系可以画成下图:

注意:如果在遍历listvector等容器中途有删除操作的话,一定要该写遍历格式:

for(auto it=lis.begin();it!=lis.end();){if(/* 条件 */){/* Something ... */it=lis.erase(it);}else{/* Something ... */it++;}
}

这是因为erase后迭代器会自动失效,而删除方法返回的就是删除元素的下一个元素。
\(4\)行写作lis.erase(it++);也可以。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐2款实用的持续集成与部署(CICD)自动化工具

前言 最近DotNetGuide技术社区交流群有不少同学在咨询:持续集成与部署(CI&CD)自动化工具有什么好用的推荐?今天大姚给大家推荐2款实用且免费的持续集成与部署(CI&CD)自动化工具,希望可以帮助到有需要的同学。 持续集成与部署工具的作用 持续集成(CI)和持续交付…

.NET周刊【8月第3期 2024-08-18】

国内文章 Roslyn 简单实现代码智能提示补全功能 https://www.cnblogs.com/lindexi/p/18365261 相信有很多伙伴热衷于编写 IDE 应用,在 dotnet 系下,通过 Roslyn 友好的 API 和强大的能力,实现一个代码智能提示是非常简单的事情。本文将和大家简单介绍一下如何使用 Roslyn 实…

视野修炼-技术周刊第98期 | Node原生支持TS

① Node 22.7 支持直接运行TS ② js 模糊搜索库 ③ Favicon 一键获取 ④ fuite - 网页内存泄露分析工具 ⑤ logtape - 0依赖日志库 ⑥ Volta 2.0 ⑦ AI 昆虫图识别欢迎来到第 98 期的【视野修炼 - 技术周刊】,下面是本期的精选内容简介 🔥强烈推荐Node 22.7 支持直接运行TS …

创建环境

python -m venv cuda cuda\Scripts\activate

最容易理解的Swin transformer模型(通俗易懂版)

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 1. 论文信息 原文地址:https://arxiv.org/abs/2103.14030 官网地址:https://github.com/microsoft/Swin-Transformer 2. 网络框架 2.1 swim VS vit 从图中可以得到,Swin相较于ViT的区别在于:Swim…

ArrayList声明,Add(), Insert();

ArrayList提供了3个构造器,通过这3个构造器可以有3种声明方式。 (1)默认构造器,会以默认大小(16位)初始化内部数组。构造器格式如下。ArrayList List = new ArrayList();//实例化一个ArrayList,命名为List;for (int i = 0; i < 10; i++)//添加10个元素到List中;{List.Ad…

【整理】【信息收集】敏感目录

一、敏感目录类型二、敏感目录收集2.1 在线查询一、敏感目录类型 数据文件、配置信息、上传目录、后台登录目录、安装页面、数据库版本、PHP版本、后台压缩包、未授权访问等。 二、 敏感目录收集 2.1 在线查询 (1)Google语法 1)site:查找与指定的网站有联系的URL。 用法:s…

centos 配置nginx

1.检查系统版本,安装nginxcat /etc/redhat-release,//这个命令会显示你的CentOS发行版名称以及大致的版本号rpm -q CentOS-release,//这将返回当前安装的CentOS版本的具体编号uname -r,//内核的完整版本字符串。2.安装nginxsudo yum install epel-release -y # 如果还没…

题解:P7952 [✗✓OI R1] 天动万象

提供一种和第一篇题解不同的理解思路。 题目分析 看到操作 \(1\):拿 dfs 序水水就行了。 看到操作 \(2\):??? 特殊情况 我们考虑一下特殊情况下操作 \(2\) 怎么处理。 假如这棵树是一条链。设从根到叶节点权值如下:(随便赋的)节点编号 1 2 3 4 5 6权值 1 2 3 4 5 6如果…

思源笔记常用代码片段

思源笔记相关设置背景色设置 :root {--b3-font-background1: #423a3a !important;--b3-font-background2: #4b3722 !important;--b3-font-background3: #203854c2 !important;--b3-font-background4: #2c5438a3 !important;--b3-font-background5: #4c525778 !important;--b3-f…