一个合格的ACMer的代码当中,都藏着哪些秘密?

article/2025/9/4 16:34:53

作者 | 梁唐       责编 | 欧阳姝黎

今天给大家聊聊C++中的头文件,之前我在写算法专题展示源代码的时候,很多小伙伴给我留言说被我的头文件中的内容震惊了。其实之所以我的头文件这么复杂,完全是因为它是我一直从大学时期acm竞赛当中沿用下来的。对于acm竞赛的选手们来说,这样的头文件其实算是小儿科了。

今天就和大家来看看,acmer 的头文件当中都藏着哪些秘密。

首先,我们先来看我完整的头文件代码。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
#define rep(i,a,b) for (int i=a;i<b;i++)
#define Rep(i,a,b) for (int i=a;i>b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)
#define mid ((l+r)>>1)
#define lson (k<<1)
#define rson (k<<1|1)
#define MEM(a,x) memset(a,x,sizeof a)
#define pii pair<int, int>
#define LL long long
using namespace std;
const int N=500005;
const long long Mod=99997867;

include部分

首先我们来看 include 的部分,我们一个一个来看,iostream 不用多说了,C++标准输入输出的头文件,包含了 C++输入输出流函数,也就是经典的 cin、cout。说到 cin、cout 多说两句,cin、cout 的开销要比 C 语言下的 scanf 和 printf 慢很多,很容易影响程序运行的性能。所以对于 acmer 来说,能用 scanf 和 printf 完成的,就绝对不会用 cin、cout。当然 scanf 和 printf 也不是最快的,还有更快的 getchar 和 putchar,所以有些玩家会自己手写循环读入 char 然后转成 int 或者是 float 的函数,当然绝大多数情况下并不需要这样。

cstdio 和 iostream 同样的功能,不过是 C 语言中的输入输出函数,不多说。

cstring 同样属于 C 语言,是 C 语言中的字符串库,有很多字符串相关的函数。同样由于性能的原因,能用 C 语言中 char[]完成的就不用使用 C++的 string。接下来的 string 库也不用多说,C++的字符串处理库。

cstdlib 库函数等同于 C 语言中 stdlib.h,封装了一些常用的库函数,如 rand、srand、free、malloc 等。

cmath 库等于 C 语言中的 math.h,封装了一些数学运算相关的库函数,如 pow、sqrt 等。

后面的 queue、vector、map、set 都是 STL 库,包含了一些比较好用的数据结构。比如 queue 中封装了 queue 以及 dequeue,和 priority_queue,也就是队列、双端队列和优先队列。vector、map、set 分别是线性表、映射表以及集合,熟练使用它们可以极大的降低编码的复杂度。

algorithm 库翻译过来就是算法库,当中自然封装了不少的算法。比如 sort 排序、reverse 翻转、next_permutation 下一个全排列、lower_bound、upper_bound 函数等。

最后一个 functional 库,用得不多,顾名思义当中封装了一些关于函数对象的操作。比如 bind、reference_wrapper 等等。

其实关于 include,有一个取巧的方法可以一次性 include 所有的头文件:

#include <bits/stdc++.h>

不过这种方法有一个小问题,并不是所有的环境都支持,尤其是在正式比赛的场合,所以一般情况下大家都是一些网络赛才会用它,我个人由于懒得区分环境,所以还是习惯自己一个一个 include。

define部分

define 是 C++ 当中非常强大的功能,它可以定义规则对代码进行替换。熟练使用 define 同样可以大大简化编码。但是要注意,凡事不能过度,如果 define 使用过多会影响程序的可读性,也可能对其他人的编码造成影响。所以很多大公司是禁止使用 define 的,我个人倒觉得其实也不用这么严肃,define 可以用,遵守规范,适当使用就可以了。

首先是这两行,是 for-loop 的 define。

#define rep(i,a,b) for (int i=a;i<b;i++)
#define Rep(i,a,b) for (int i=a;i>b;i--)
#define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++)

rep 是 repeat 的缩写,使用的时候只需要 rep(i, a, b)就可以代替冗长的 for 循环的编写,其中 i 是循环变量,a 和 b 分别是循环的上下界,注意是左闭右开区间。

Rep 也是同样的逻辑,只不过是倒序的循环。

foreach 使用的是 C++11 的新特性,可以实现自动迭代,用的不多,在一些场景下非常方便。

#define mid ((l+r)>>1)

这行用在二分查找当中,左边界是 l,右边界是 r,那么它们的中点就是(l + r) / 2,用位运算表示就是:(l + r) >> 1。例子:

# define之前
while (l + 1 < r) {int m = (l + r) >> 1;if (a[m] <= v) {l = m;}else {r = m;}
}# define之后
while (l + 1 < r) {if (a[mid] <= v) {l = mid;}else {r = mid;}
}
#define lson (k<<1)
#define rson (k<<1|1)

这两行主要是用在线段树上,因为 C++ 往往不使用类来实现线段树,而是通过数组来模拟实现。在线段树当中,如果某一个节点的 id 是 u,那么它的左孩子是 2 x u,右孩子的 id 是 2 x u + 1,用位运算来表示就是 u << 1 和 u << 1 | 1。

#define MEM(a,x) memset(a,x,sizeof a)
#define pii pair<int, int>
#define LL long long 

最后三行放在一起说,第一行是 memset 的缩写,memset 可以用来初始化数组。pii 缩写了 pair<int, int>,pair 是用来绑定两个变量的数据结构。最后是 LL 缩写了 long long,long long 是 64 位的 int,它的范围要比 int 大得多。

关于类型的重定义,这里使用 define 并不是非常好,更好的方法是使用 typedef,例如上面的 pair 和 long long 可以写成:

typedef pair<int, int> pii;
typedef long long LL;

相比 define 之下这样更规范一些,因为 define 是生硬的字符串替换,而 typedef 则是类型别名,能够被编译器检查,所以能使用 typedef 还是使用 typedef。

尾声

除了上面用到的这些头文件之外,还有一些更高端的用法,比如一些模板类,以及一些常用的算法,比如 gcd 等等。但我个人觉得意义不是非常大,对于面试、笔试的代码环节来说,以上的这些头文件已经足够使用了。

☞苹果iCloud(贵安)数据中心投入运行;网易公布不当言论HR处理结果:已开除;OceanBase数据库将开源|极客头条☞程序员35岁就该退休了吗?☞从“不作恶”到“门就在那边”,谷歌 AI 伦理史

http://chatgpt.dhexx.cn/article/ooBbFwCQ.shtml

相关文章

ACM模板(从小白到ACMer的学习笔记)

写在开头&#xff1a; 2020年ICPC银川站&#xff0c;现场赛&#xff0c;第三题的字典树没能过&#xff0c;首站打铁&#xff0c;不过这一场也让我看到铜牌其实没有想象中的那么难。 2020年ICPC沈阳站&#xff0c;现场赛&#xff0c;封榜后过两题&#xff0c;铜首&#xff0c;I题…

【转】 如何提高自己的acm个人能力

转载自 简单de数字 最终编辑 fading_code by zfy0701 本来以为HNU的huicpc035和我一样退役了&#xff0c;后来听说他组成了新的footman队&#xff0c;于是又关注了下他。 035体现了两个我觉得非常重要的品质&#xff1a; 1、刻苦的训练 2、有效的训练 &#xff08;本文将主…

ACMer必看的基础算法(附经典例题)

文章目录 一、排序算法1.冒泡排序2.选择排序3.快速排序4.桶排序 二、递归算法三、递推算法四、贪心算法五、动态规划基本模型区间dp背包问题01背包完全背包多重背包 六、分治算法二分三分 七、补充STL的简单应用结构体 一、排序算法 1.冒泡排序 【基本思想】 基本思想为两两比…

反向代理与正向代理区别

正向代理与反向代理的区别 正向代理是客户端与正向代理客户端在同一局域网&#xff0c;客户端发出请求&#xff0c;正向代理 替代客户端向服务器发出请求。服务器不知道谁是真正的客户端&#xff0c;正向代理隐藏了真实的请求客户端。 反向代理&#xff1a;服务器与反向代理在同…

Nginx反向代理与正向代理配置

一、Nginx主要功能 1、Nginx 简介 Nginx是一款轻量级的Web 服务器 、反向代理服务器及电子邮件(IMAP/POP3)代理服务器。主要有反向代理,负载均衡等功能。 官方网站:nginx news Nginx是一款免费开源的高性能 HTTP 代理服务器及反向代理服务器(Reverse Proxy)产品,它高…

如何解释反向代理与正向代理

概念 首先看看说明图&#xff0c;先有一个整体的理解。 正向代理&#xff08; Forward Proxy &#xff09;&#xff1a; 是指是一个位于客户端和原始服务器之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c; 客户端向代理发送一个请求并指定目标(原始服务器)&am…

反向代理设置

折腾家庭服务器&#xff0c;因只有一个公网ip&#xff0c;还要尝试设置私有云&#xff0c;博客&#xff0c;论坛&#xff0c;以及练习flask编程&#xff0c;又不想写各种端口访问&#xff0c;计划采取的方案是设置一个反向代理&#xff0c;使用子域名访问各个服务。 一、什么是…

知识积累3:什么是反向代理,如何区别反向与正向代理

一直对反射代理的反向不知道如何理解&#xff0c;经过百度知道&#xff0c;再结合下面这幅图&#xff0c;总算弄清楚一点了。简单的说从一个局域网出来到服务端为正向&#xff0c;从客户端要进入一个局域网为反向 概念&#xff1a; 反向代理&#xff08;Reverse Proxy&#xf…

正向代理和反向代理概念及区别

正向代理和反向代理 文章目录 正向代理和反向代理前言正向代理正向代理用处 反向代理反向代理用处 总结(正反向代理的区别) 前言 总是搞不懂正向代理和反向代理应用场景,今天专门来整理一下 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 正向代理 正…

nginx反向代理和正向代理的区别

nginx反向代理和正向代理的区别是什么&#xff1f;下面本篇文章就来给大家介绍一下&#xff0c;希望对你们有所帮助。 什么是正向代理&#xff1f; 正向代理是一个位于客户端和原始服务器(origin server)之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向…

Nginx正向代理与反向代理详解

一、介绍 实践中客户端无法直接跟服务端发起请求的时候&#xff0c;我们就需要代理服务。代理可以实现客户端与服务端之间的通信,我们的Nginx也可以实现相应的代理服务。代理分为正向代理和反向代理,此文就来演示一下Nginx配置正向代理和反向代理的场景。 二、正向代理和反向…

正向代理与反向代理的理解以及区别

正向代理与反向代理 参照了知乎以及百度的一些列子&#xff0c;以下说一下自己的理解 - 正向代理 先搭建一个属于自己的代理服务器 1、用户发送请求到自己的代理服务器 2、自己的代理服务器发送请求到服务器 3、服务器将数据返回到自己的代理服务器 4、自己的代理服务器…

nginx正向代理+反向代理

目录 Nginx工作原理及模块介绍​​​​​​​ Nginx原理 负载均衡反向代理 Nginx WEB服务器最主要就是各种模块的工作&#xff0c;模块从结构上分为核心模块、基础模块和第三方模块&#xff0c;其中三类模块分别如下&#xff1a; 核心模块&#xff1a;HTTP模块、EVENT模块和…

Nginx 正向代理和反向代理

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

什么是正向代理和反向代理

什么是正向代理和反向代理 1. 正向代理2. 反向代理3. 两者的区别 1. 正向代理 正向代理隐藏真实客户端 正向代理&#xff0c;就是一个位于客户端和原始服务器之前的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向代理发送一个请求并且指定目标&#xff08;…

nginx--正向代理、反向代理及负载均衡(图解+配置)

目录 学习背景一、代理服务二、正向代理1.1 什么是正向代理&#xff1f;1.2 如何实现nginx正向代理&#xff1f;1.3 客户端访问&#xff08;验证正向代理&#xff09; 二、反向代理2.1 什么是反向代理&#xff1f;2.2 nginx实现反向代理 三、负载均衡3.1 什么是负载均衡&#x…

正向代理和反向代理详解(纯小白必看 最好懂的白话文教程)

概要 习惯性的bb几句 本文主要介绍正向代理和反向代理的区别&#xff0c;如何区分&#xff0c;各自的好处&#xff0c;还有一些应用场景 主要是白话文的内容&#xff0c;不会有太多专业术语&#xff0c;主要是面向纯小白&#xff0c;做个解疑&#xff0c; 部分地方稍微不严谨&…

nginx代理(正向代理和反向代理)

正向代理 是一个位于客户端和原始服务器(origin server)之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向代理发送一个请求并指定目标(原始服务器)&#xff0c;然后代理向原始服务器转交请求并将获得的内容返回给客户端&#xff08;目的是为了保护客户端…

反向代理是什么意思?正向代理和反向代理的区别是什么?

一文说清楚正向代理与反向代理的区别 什么是正向代理&#xff1f;什么是反向代理&#xff1f;它们的区别是什么&#xff1f;看完本文就清楚了… 首先&#xff0c;从字面上理解&#xff0c;代理的意思是代替办理&#xff0c;就是一方委托另一方办事&#xff0c;在计算机网络的世…

正向代理和反向代理有什么区别?什么是正向代理?什么是反向代理?正向代理和反向代理详解。

一、正向代理&#xff1a; 当用户想访问某一网址时&#xff0c;用户先访问代理服务器&#xff0c;然后由代理服务器向目标网址发送请求最终将数据返回代理服务器&#xff0c;最后代理服务器将数据返回给用户这一过程我们称之为正向代理。 正向代理它代理了客户端&#xff0c;相…