📅  最后修改于: 2023-12-03 15:27:22.703000             🧑  作者: Mango
竞争编程是指,参赛者在规定的时间内(一般为数小时到数天),独立完成所给出的若干个问题(即“比赛题目”)的设计与实现,通过对竞赛系统的自动评测程序或人工评测进行测试,最终得到比赛成绩和排名的竞争形式。以下是一些可以帮助初学者在竞争编程中编写更高效、更简洁代码的C++技巧。
当写C++代码时,通常要引入一些标准头文件如<iostream>
和专用头文件如<vector>
和<string>
。虽然可以在每个文件中都单独包含所需的头文件,但更好的方式是将所有必需的头文件一次性包含于一个公共文件中,如下所示:
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> v;
v.push_back(1);
v.push_back(2);
cout << v[0] << " " << v[1] << endl;
return 0;
}
当然,这种方法不够安全,因为<bits/stdc++.h>
包含了所有标准头文件,可能会导致一些命名冲突。所以如果想保证代码的安全性,可以逐个包含所需的头文件。
typedef
和define
来简化代码C++中有许多长而复杂的数据类型,如std::map<int, std::pair<int, int>>
。使用typedef
和define
可以简化代码,使其更易于理解和编写,例如:
typedef std::map<int, std::pair<int, int>> MPP;
#define pii std::pair<int, int>
#define mp(a, b) std::make_pair(a, b)
这样,以后可以用MPP
代替std::map<int, std::pair<int, int>>
:
MPP myMap;
myMap[1] = mp(2, 3);
std::priority_queue
是一个可以用于实现堆的STL容器,很多初学者在堆操作时可能会犯迷糊。我们可以在定义std::priority_queue
时添加自定义的比较方式,比如:
struct node{
int x, y;
} a[100001];
struct cmp{
bool operator()(int i, int j) {
return a[i].x > a[j].x;
}
};
std::priority_queue<int, std::vector<int>, cmp> pq;
这里的自定义比较是指按照a[i].x
的从小到大顺序将节点插入堆中。
vector
作为布尔类型数组的替代品如果需要一个布尔类型数组,用std::vector<bool>
比bool arr[N]
更省空间。虽然bool
类型只需要1字节,但在使用bool arr[N]
时,可能会占用更多的内存空间,例如:
const int maxn = 10000000;
bool prime[maxn];
int main() {
memset(prime, true, sizeof(prime)); // 慢
return 0;
}
相比之下,使用std::vector<bool>
会更省空间:
const int maxn = 10000000;
std::vector<bool> prime(maxn, true);
int main() {
return 0;
}
auto
关键字使用auto
关键字可以自动推导出表达式的类型,从而简化代码。例如:
std::vector<int> a = {1, 2, 3};
for (auto i : a) {
cout << i << " ";
}
这里可以用auto
关键字自动推导变量类型,从而避免了需要手动指定一个类型的麻烦。为了保证代码的可读性,应该适量地使用auto
关键字。
将循环变量定义在循环语句中可以提高代码的可读性和效率。例如,下面的代码:
for (int i = 0; i < n; ++i) {
// ...
}
比这种代码:
int i;
for (i = 0; i < n; ++i) {
// ...
}
更易于阅读和理解。另外,将循环变量定义在循环语句中还可以避免变量作用域和命名冲突的问题。
static
和const
关键字使用static
和const
关键字可以提高代码的可读性和效率。static
关键字可以在局部变量和函数中防止变量和函数被频繁创建和销毁,从而提高效率。const
关键字可以在变量定义时防止变量被修改,从而增加代码的安全性和可读性。例如:
class Solution {
public:
static const int MAXN = 100001;
static const int MOD = 1000000007;
static const double EPS = 1e-9;
static const std::string STR;
int add(int a, int b) {
return (a + b) % MOD;
}
};
const std::string Solution::STR = "Hello";
emplace_back()
代替push_back()
std::vector
的push_back()
函数会将元素复制到容器中,从而占用一定的时间和空间。而emplace_back()
函数可以直接在容器中创建元素,从而避免了元素拷贝和内存传输,提高了效率。例如:
typedef std::pair<int, int> PII;
std::vector<PII> v;
v.emplace_back(1, 2);
cin
和cout
进行优化读入和输出通常是程序中的一个瓶颈,所以优化输入输出可以提高程序的速度。有两种方法可以优化输入输出:一是关闭同步流,二是使用快速IO。例如:
// 关闭同步流
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
// 使用快速IO
printf("%.6lf\n", ans);
可以通过关闭同步流、断开cin/cout
的联系和使用printf()
和scanf()
等函数来提高输入输出效率。但是,这种方法的代码可读性不如使用C++的IO流,建议在能够忍受一定时间的输入输出延迟的情况下,尽量避免使用这些快速输入输出方法。
以上是一些可以帮助竞争编程初学者编写更高效、更简洁代码的C++技巧。