本人的OI代码规范
本文为本人在OI竞赛中的一些代码规范。
1. include
本人一般只使用一个头文件 bits/stdc++.h
万能头,且放在代码的开头。
#include<bits/stdc++.h>
2. using
一般情况下,本人通常都会使用 std 命名空间。
using namespace std;
3. 常量
一些常量(如 \(N\):数据最大范围、\(INF\):int 类型最大值等),通常定义在 using 和结构体之间。
const int N=50;
4. 结构体
结构体的定义区域位于常量和变量之间。一般来说,命名基本都是下划线命名法。
struct coord{
int x;
int y;
int step;
};
5. 变量
变量定义区域为结构体和函数之间,命名风格为下划线命名法。
int a,this_is_a_test;
6. 函数
除了递归函数,一般都会加上 inline
声明。采用下划线命名法,每 2 个函数之间空一行,采用下划线命名法。
inline bool check(int x){
//do sth
}
void dfs(int t){
//do sth
}
7. 花括号
一般的花括号是左花括号不换行,右花括号换一行。
inline int this_is_a_test(){
//do sth
}
8. 注释
我有时候会在一些难理解的或比较少写的地方做注释,一些经常写的或自己心知肚明的就不会打注释。
int var; //var 代表 sth
9. 其他
我的风格主要参考 Webkit 风格,变量之间一般不空格(即紧凑排列),各部分(就是上面的每个大标题)之间必须空一行。代码缩进为 4 格空格(Tab)。
10. 示例
代码示例以洛谷P5076 【深基16.例7】普通二叉树(简化版)的代码为例。
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const int INF=0x7fffffff;
struct node{
int data;
int size;
int cnt;
int lft;
int rgt;
}tree[N];
int q,op,x,cnt;
void add(int root,int v){
tree[root].size++;
if(tree[root].data==v){
tree[root].cnt++;
return;
}
if(tree[root].data>v){
if(tree[root].lft!=0){
add(tree[root].lft,v);
}else{
cnt++;
tree[cnt].data=v;
tree[cnt].size=tree[cnt].cnt=1;
tree[root].lft=cnt;
}
}else{
if(tree[root].rgt!=0){
add(tree[root].rgt,v);
}else{
cnt++;
tree[cnt].data=v;
tree[cnt].size=tree[cnt].cnt=1;
tree[root].rgt=cnt;
}
}
}
int pre(int root,int v,int ans){
if(tree[root].data>=v){
if(tree[root].lft==0) return ans;
else return pre(tree[root].lft,v,ans);
}else{
if(tree[root].rgt==0) return tree[root].data;
if(tree[root].cnt!=0) return pre(tree[root].rgt,v,tree[root].data);
else return pre(tree[root].rgt,v,ans);
}
}
int past(int root,int v,int ans){
if(tree[root].data<=v){
if(tree[root].rgt==0) return ans;
else return past(tree[root].rgt,v,ans);
}else{
if(tree[root].lft==0) return tree[root].data;
if(tree[root].cnt!=0) return past(tree[root].lft,v,tree[root].data);
else return past(tree[root].lft,v,ans);
}
}
int queryrk(int root,int v){
if(root==0) return 0; //没有排名
if(v==tree[root].data) return tree[tree[root].lft].size;
if(v<tree[root].data) return queryrk(tree[root].lft,v);
return queryrk(tree[root].rgt,v)+tree[root].cnt+tree[tree[root].lft].size;
}
int kth(int root,int rk){
if(root==0) return INF;
if(tree[tree[root].lft].size>=rk){
return kth(tree[root].lft,rk);
}
if(tree[tree[root].lft].size+tree[root].cnt>=rk){
return tree[root].data;
}
return kth(tree[root].rgt,rk-tree[root].cnt-tree[tree[root].lft].size);
}
void erase(int root,int v){
tree[root].size--;
if(tree[root].data>v){
erase(tree[root].lft,v);
}else if(tree[root].data<v){
erase(tree[root].rgt,v);
}else{
tree[root].cnt--;
}
}
int main(){
cin>>q;
while(q--){
cin>>op>>x;
switch(op){
case 1:
cout<<queryrk(1,x)+1<<endl;
break;
case 2:
cout<<kth(1,x)<<endl;
break;
case 3:
cout<<pre(1,x,-INF)<<endl;
break;
case 4:
cout<<past(1,x,INF)<<endl;
break;
case 5:
if(cnt==0){
cnt++;
tree[cnt].cnt=tree[cnt].size=1;
tree[cnt].data=x;
}
else add(1,x);
break;
default:
break;
}
}
return 0;
}