我的码风,欢迎对比 awa~


缺省源

从几个月前以后的代码基本上都用的这个缺省源:

//By: Luogu@rui_er(122461)
#include <bits/stdc++.h>
using namespace std;

int main() {

    return 0;
}

头文件

在 2020.2 以前,使用 iostream,其他要用的时候加。那时候确信万能头不是个好东西……嗯,真香。

现在只使用万能头,开发项目的时候可能加上 time.hwindows.h

namespace std

一般情况使用:

using namespace std;
cout<<"I AK IOI"<<endl;

而不是:

using std::cin;
using std::cout;
using std::endl;
cout<<"I AK IOI"<<endl;

或者:

std::cout<<"I AK IOI"<<std::endl;

输入输出

对于不卡常情况,一律使用 scanf / printf,除非使用 std::string 类型。对于数组的读入,使用 &a[i] 而不是 a+i

int n, a[100];
scanf("%d", &n);
for(int i=1;i<=n;i++) scanf("%d", &a[i]);

对于卡常情况或特殊需求的字符串操作,使用下面版本的快读:

int read() {
    int x = 0, k = 1;
    char c = getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') k = -1;
    for(;isdigit(c);c=getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * k;
}

除非特别毒瘤情况,不会使用快写。

堆、栈、队列、双端队列、单调队列

这些一律使用 STL 不手写。

queue<int> q;

括号

对于函数、条件分支或循环语句的大括号,左括号与声明在同一行,之间空一格,右括号换行,中间缩进一个 Tab 或 $4$ 个空格。

for(int i=1;i<=10;i++) {
    printf("%d ", i);
}

对于函数、条件分支或循环语句的小括号,或者数组等的中括号,不空格。

a[10];
f();

标点间空格

函数参数逗号前不空格,逗号后空一格。

f(1, 2, 3);

表达式中符号和变量之间空一格,括号内不空格,括号外空格。

int a = (1 + 2 * 3) >> 1;

函数体中参数若为复杂表达式,不空格。

f(1, (a+b*c)/2, 4);
ceil(4.2*a/1.1) * 9;

条件分支或循环语句参数规则同上,for 循环不空格。(我也不知道为什么,反正写习惯了)

while(a > 0 && a < n);
for(int i=1;i<=n;i++);
if(a & 1);

命名空间和结构体的使用

对于一题中不同的部分分,使用 namespace 区分,调用的功能函数为 main()

namespace _30pts {
    int a, b;
    void main();
}
namespace _100pts {
    int a, b;
    void doSth();
    void main();
}
int main() {
    if(judge30pts) _30pts::main();
    else _100pts::main();
}

对于一道杂糅题需要用到很多算法,可能使用 namespace 区分。

namespace BIT {
    // do sth
}
namespace CDQ {
    // do sth
}

结构体中写全构造函数与析构函数,重载运算符可能采用下面两种:

struct Node {
    int l, r;
    Node() {}
    Node(int a, int b) : l(a), r(b) {}
    ~Node() {}
    bool operator < (const Node &a) const {} // 方法 1
//  friend bool operator < (const Node &a, const Node &b) {} // 方法 2
};

因为踩过传整个结构体爆空间的坑,所以采用传输 const Node &a 地址的形式。

一般不使用类,用结构体代替。

存图、树

二叉树使用数组存储,左儿子 x<<1,右儿子 x<<1|1

树或图一般采用链式前向星,有时采用邻接表。

变量、函数名

循环内指示变量从 i 开始向上。

无关紧要或不好取名的变量用 ___ 等。

多组数据用 T

其他情况,有时按照一个字母好记的,有时按照功能:

int n, m;
for(int i=1;i<=n;i++);
void BaiduFirstSearch(); // bfs
void FastFastTle(); // fft

C++11 语法、指令集

除非懒,或者极其复杂,不使用 C++11 语法。

除非卡常数,不使用指令集。CF896E 指令及暴力草过去不算啊(

STL

经常使用 STL,声明时有用尖括号括住的变量类型,在 STL 类型(如 queue)与变量类型(如 <int>)之间不空格,在变量类型与变量之间空格。

queue<int> qwq;

对于下面这种复杂的情况,为了避免两个大于号被识别成右移,中间空一格。

queue<pair<int, pair<int, int> >, vector<pair<int, pair<int, int> > >, greater<pair<int, pair<int, int> > > > qaq;

long long

经常分不清那些变量要用 ll,如果存在变量可能爆 int,就全开 ll。

这么开:

typedef long long ll;

而不是:

#define ll long long

或者:

long long a;

数据范围

数据范围一般定义成常量。

这么定义:

const int N = 1e5+5;

而不是:

#define N (int(1e5+5))

宏定义

一般不使用宏定义。

空行

头文件与 namespace 之间不空行,namespace 与数据范围之间不空行,数据范围后空一行。

所有变量一般声明在数据范围后、一切函数前。变量声明之间不空行,变量与函数间空一行。同一个功能的不同操作函数之间不空行,不同功能函数之间空一行。主函数前空一行。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;

int n, m;
double ans;

int mian() {return 1;}

int main() {}

压行

只有一行内容的函数、循环或条件分支将被压进一行,其他不压行。

一般不使用逗号,而是两个分号。

为了方便 CF 减少罚时,有时会写 return puts("0"), 0;

for(int i=1;i<=n;i++) scanf("%d", &a[i]);
for(int i=1;i<=n;i++) {
    scanf("%d", &b[i]);
    ans += a[b[i]];
}

杂项

貌似没啥杂项……