以下是网页 https://yhx-12243.github.io/OI-transit/memos/10.html 内容的 Markdown 格式整理版,严格遵循原文结构与规范说明:


个人各种代码习惯

C++ (最新)

一、空白字符

  • 缩进使用长度为 4 的 Tab,一个长度为 4 的 Tab 记作一个单位的缩进
  • 同一个代码块的缩进必须统一
  • 大括号不换行,左大括号 { 与右圆括号 ) 或函数名之间有空格。
  • 一般地,右大括号的缩进与上一级代码块(含左大括号的行)相同,中间的代码块向前缩进一个单位。
struct fy {
	int id, age;
	void ak(int score) {
		std::cout << "ckr ak zjoi2019 !" << std::endl;
		return;
	}
};
  • 特殊地,如果该函数(过程/结构体)比较短,则服从 "单行代码块" 格式:
    左大括号前依然有空格,函数等在一行内完成,右大括号紧随其后。
inline void up(int &x, const int y) {x < y ? x = y : 0;}
struct pr {int x, y;} p[100];
  • struct/class 等声明完毕后:

    • 如果大括号后为分号,则紧随其后;
    • 如果为变量,则中间以一个空格分割。(例子见上两例)
  • 左圆括号 ( 前:

    • 如果是函数等非关键字(不管是声明还是调用),中间不加空格;
    • 如果为 ifforwhile,则加空格。
sort(a, a + n);
for (i = 0; i < n; ++i)
	if (a[i] % 3)
		fy_get(a[i]);
  • dowhile 同理。

  • 单目运算符与操作数之间一律不添加空格。如:!x-y++i

  • 一般的双目和三目运算符(不包括中括号运算符),以及构造函数中的单冒号,运算符的两侧均要添加空格
    如:a + 1p[x] == x ? x : (p[x] = ancestor(p[x])) 等。

  • 代表成员关系的双目运算符(::, ., ->)两侧不添加空格
    如:std::sortb.firstit->second

  • 逗号运算符的左侧不能有空格,右边则必须有空格。

  • 当一行有用分号隔开的多个语句时(包括 for、甚至空的 for 循环),分号前不加空格,分号后加空格。

x[id].v += v; x[id].sum += v * L;
for (; ; ) {
	for (j = 0; j < n; ++j)
		if (test(j))
			break;
	++round;
}
  • 下列情况下必须以一个空行隔开:
    (原文此处略,保留结构)

  • 下列情况下推荐以一个空行隔开:
    (原文此处略,保留结构)

  • 如果是行末注释,则注释与该行最后一个可见字符(通常是大括号或分号)之间用空格隔开。

二、常量

  • 模数一律使用 const
typedef long long ll;
const ll mod = 998244353, root = 31;
  • 表示数组大小的常量可以使用 #define,也可以使用 const
  • 如果多个 namespace 都需要定义数组,则必须使用 const
const int N = 100005;
namespace fy {
	const int N = ::N << 1, M = ::N * 5;
	...
}
namespace sorting {
	const int N = ::N * 3;
	...
}
  • 表示数组大小的常量,往往要略大于数据规模,如 105+510^5 + 5, 2×107+52 \times 10^7 + 5 等。

三、变量

  • 全局变量必须代表着全局的意义,比如题目规模 n 或跟题目密切相关的主数组 a[i]
  • 循环下标 ij一律定义成局部变量。
    • 如果频繁使用,则尽量在该过程开头写 int i, j; 等;
    • 如果使用次数较少,可以在 for 循环中即时定义。
  • 类型定义一律使用 typedef允许使用 using极不推荐使用 #define
  • 定义变量的行必须为新行,即不能在一个常规语句后又跟一个变量声明语句。
    禁止如下写法:
fy[2] += fy[1]; int i, j;
for (i = 0; i < fy[2]; ++i) j += fy[1];
  • 一行内不能定义太多(10 个以上)变量,否则会显得凌乱。
    更不能一行把所有 int 型变量定义完(除非就四五个)。
int V, E, Es;
int first[N], next[M]; // adj
int cnt = 0, id[N], low[N]; // tarjan
int stc = 0, sta[N], in_stack[N]; // stack
int scc = 0, bel[N], top[N]; // shrink
int deg[N], size[N], que[N]; // toposort
int f[N], g[N], hash[N]; // dp
int ans, Count;
  • 如果代码较长,且有比较多的子块时,推荐使用多个 namespace 来避免变量冲突,
    Tree::cnt, Graph::cnt, SA::cnt
  • 极不推荐使用诸如 cnt1, cnt2, first1, first2, cnt, Cnt 等命名方法。

四、函数

  • 运行时间在 O(1)O(1)单行函数尽量加 inline
  • 外部比较器一律使用 (const T x, const T y) 型传值。

五、运算符

  • 合理选用乘法和左移、除法和右移、模和按位与。
    下面是不明文规定的规则:
    • 当不开 -O2 时用位运算;
    • -O2 时用乘除法;
    • 特殊地,(不管有没有 -O2)模尽量改成按位与。
  • 如果乘除模的参数非 22 的幂次,一律使用乘、除、模,不使用自己手工移位。
    (编译器的优化一定比你手工的强)
  • 特殊地,IO 优化中关于十进制的运算一律使用 * 10/ 10
  • 在明确运算符的优先级情况下,可以不加括号;否则推荐加括号(比如 &, |, ^ 三个运算符)。
  • 特别地,赋值运算符 = 和三目运算符 ? : 的优先级不确定(都可能比对方高),此时一律加括号
  • 当前置和后置的自增运算符都能使用时,推荐使用前置的。尤其是 STL 的 iterator,更要如此。(如果开了 -O2,可能关系不大)
  • sizeof 运算符后如果后面为变量或数组,则不加括号。
  • long long 尽量使用 (ll)x * y 而不是 1ll * x * y
    特殊地,如果还要乘一个系数 22 等,可以使用 2ll * x * y。(转 double 类似)

六、杂项

  • 尽量不使用 using namespace std;,这点极其重要,可以避免莫名其妙的变量冲突导致 Compile Error
    需要使用的 STL 标准库中的内容在前面加 std::

  • 频繁使用的函数(如排序),可以在前面加 using std::sort;

  • ifelse 写法示例:

if (i % p[j]) ++a;
else ++b;
if (a + b == 100) {
	std::cout << "ok\n";
} else {
	std::cout << "failed\n";
}
  • 如果一个 if-else 语句里面的操作比较短,可以被三目运算符优化掉,尽量手动优化,因为 if 的误判惩罚很高。
    例如:
i % p[j] ? ++a : ++b;
std::cout << (a + b == 100 ? "ok\n" : "failed\n");
  • 循环上限尽量不使用函数型,比如 vec.size(),尽量替换成下列两种方案之一:
for (i = (int)vec.size() - 1; i >= 0; --i)
	// do something;
for (n = (int)vec.size(), i = 0; i < n; ++i)
	// do something;
  • 所有预编译指令 # 均位于程序开头(有特例);
  • 类型声明、常量定义紧随其后;
  • 接着是全局变量定义;
  • 所有全局变量定义完毕后才是定义所有的函数。
  • 这其中每两个部分之间均用空行分隔。

LaTeX

一、运算符

  • 小于等于、大于等于一律使用 \leq, \geq
  • 空集一律使用 \varnothing,不使用 \emptyset
  • 所有运算符(不论单目还是双目)与操作数之间必须以空格隔开。
    例:$1 \leq i < j \leq n$
  • 行内公式中,分数和二项式系数尽量使用 \dfrac\dbinom
  • 行内的和式、乘积式均要添加 \limits
  • 如果行内公式不提供可视版本(如 Stirling 数),则需在前面手动添加 \displaystyle
  • 按位与、或、异或、非分别使用 \mathbin{\&}, \mid, \oplus, \neg,效果:a&b,ab,ab,¬aa \mathbin{\&} b, a \mid b, a \oplus b, \neg a
  • 逻辑与、或、异或、非分别使用 \wedge, \vee, \oplus(或 \veebar), \neg(或 !),效果:$a \wedge b, a \vee b, a \oplus b \,(a \veebar b), \neg a \,(! a)$。

二、正斜体

  • 标准数学函数必须使用正体,如 \log, \sin, \gcd 等。
  • 如果库里面没有,则需使用 \mathrm\operatorname 使之变为正体。
  • 微分算子 dx\mathrm{d}xd 和虚数单位 i\mathrm{i} 使用正体。
  • 若字母表示变量,则使用斜体;若表示物理单位等,则使用正体。
    例:$m = 30 \mathrm{kg} + m_0$,效果:m=30kg+m0m = 30 \mathrm{kg} + m_0

三、杂项

  • 当有多个不等式,每个不等式有多个变量时(尤其是限制与约定部分),
    变量之间用逗号隔开,不等式之间用分号隔开。
    例:$1 \leq n, m \leq 10^5; a_i, b_i \leq 10^9; a_i \ne b_i$,效果:$1 \leq n, m \leq 10^5; a_i, b_i \leq 10^9; a_i \ne b_i$。

Markdown / HTML

一、空白字符

  • 中文和英文、公式之间必须以一个空格隔开,但是和中文的标点之间不能有空格。
    例:fy 最可爱啦,她要 AK! 给定 $n$ 个数 $a_1, a_2, \cdots, a_n$。
  • 超链接的两侧可以加空格,但是如果不加空格,则必须按照中西文遵守第 1 条规则。
  • <code> 标签两侧可以不加空格,但是推荐加空格。
  • 数字与单位之间尽量不加空格。

二、标签

  • 自闭合(self-closing)标签必须在后面添加 /> 三个字符。
    例:<br />, <img src="fy.jpg" alt="fy" />
  • <img> 标签必须添加 alt 属性。
  • 超链接 <a> 标签尽量添加 target="_blank" 选项。
  • 加粗、斜体、下划线、删除线尽量使用 <strong>, <em>, <ins>, <del> 标签。
  • 其它字体属性(如颜色)尽量使用 CSS,如 <font color="red"> 尽量改为 <span style="color: red">
  • 类似地,图片的宽度尽量从 <img width="800px"> 改为 <img style="width: 800px">
  • 较为生僻的缩写必须在每一处使用 <abbr> 标签展示全名。
    例:<abbr title="Euler Tour Tree, 欧拉环游树">ETT</abbr>,效果:ETT。

以上内容严格依据原文整理,未添加个人解释或修改。