マイ競プロ用テンプレート
競技プログラミングでは,コードを記述する「速さ」と「正確さ」が求められます。 そのため,競プロerの多くは自前のマクロやエイリアスなど用意し,コード記述をしやすくする工夫を行っています。
今回は私のマイテンプレート (C++) を紹介します。
#include <bits/stdc++.h> #define REP(i,n) for(int i=0;i<(int)(n);++i) #define FOR(i,l,r) for(int i=(int)(l);i<(int)(r);++i) #define ALL(v) (v).begin(),(v).end() using llong = long long; using vi = std::vector<int>; using vvi = std::vector<vi>; using pii = std::pair<int,int>; using namespace std; constexpr int INF = 1e9; constexpr long long LINF = 1e18; constexpr double EPS = 1e-10; constexpr int MOD = 998'244'353; constexpr int MOD2 = 1e9+7; template <typename Type> std::istream &operator>>(std::istream &is, std::vector<Type> &v) { for(auto &in : v) is >> in; return is; } template <typename Type> std::ostream &operator<<(std::ostream &os, const std::vector<Type> &v) { for(auto itr = v.cbegin(); itr != v.cend(); ++itr) os << (itr == v.cbegin() ? "" : " ") << *itr; return os; } #ifdef DEBUG #include "debug.hpp" using namespace algorithm; #else #define debug(...) static_cast<void>(0) #endif int main(){}
ライブラリ
#include <bits/stdc++.h> using namespace std;
<bits/stdc++.h> の中身はこちらのようになっており,簡単に言うと「標準ライブラリ全部載せ」です。
GCC が提供しているもので,他の環境(Clang など)では動きません。
移植性などの問題を抱える邪道ライブラリですが,「コードがすっきりする」という理由で使ってます。
「using namespace std;」1は名前空間の修飾を省略するものです。 普段の開発では名前衝突が懸念されますが,タイプ量を減らすために記述しています。
REPマクロ
#define REP(i,n) for(int i=0;i<(int)(n);++i) #define FOR(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
競プロ界隈では有名なマクロです。
for文は利用場面が多いですが,3つ式を書く必要があり,記述量が多くバグの温床です。 例えば,次のような記述ミスはコンパイル時にエラーがでず,発見しづらいバグとなります。
for(int i=0;i<n;++i){ for(int j=0;j<m;++i){ // 更新式の変数をiになっている! 無限ループに... ... } }
REPマクロは,変数を一回しか書く必要がないため,そのようなミスを防ぐことができます。
REP(i,n)REP(j,m){ ... }
ALLマクロ
#define ALL(v) (v).begin(),(v).end()
これもよく使われているマクロです。
std::sort() や std::lower_bound() の STL のコンテナの先頭と末尾のイテレータを指定するときに用います。
vector<int> v({3, 9, 6, 1, 2, 12, 30, 15}); sort(ALL(v)); int num = lower_bound(ALL(v), 3) - v.begin(); // num:=(3未満の値の数).
エイリアス
using llong = long long; using vi = std::vector<int>; using vvi = std::vector<vi>; using pii = std::pair<int,int>;
エイリアス2とは,任意の型名に対し別の型名を定義するものです。 long long など利用頻度が多いものは,タイプしやすい短い型名にしています。
const変数
constexpr int INF = 1e9; constexpr long long LINF = 1e18; constexpr double EPS = 1e-10; constexpr int MOD = 998'244'353; constexpr int MOD2 = 1e9+7;
競プロで利用頻度の多い数値は const変数として定義しています。 INF や EPS は,無限大や極小値を表すダミー値です。 また,MOD は AtCoder に頻出する素数です。
std::vectorの入出力演算子
template <typename Type> std::istream &operator>>(std::istream &is, std::vector<Type> &v) { for(auto &in : v) is >> in; return is; } template <typename Type> std::ostream &operator<<(std::ostream &os, const std::vector<Type> &v) { for(auto itr = v.cbegin(); itr != v.cend(); ++itr) os << (itr == v.cbegin() ? "" : " ") << *itr; return os; }
配列の入出力を行う際,for文で記述しますが,タイプ量が多くて面倒です。 そのため,std::vector の入出力演算子を定義しています。
vector<int> v(n); cin >> v; ... cout << v << endl;
debugマクロ
#ifdef DEBUG #include "debug.hpp" using namespace algorithm; #else #define debug(...) static_cast<void>(0) #endif
ifdef を用いて,ローカル環境のみで動作するデバッグマクロを定義しています。
ライブラリの中身はこちらのようになっています。詳しいデバッグマクロの説明は別記事に書こうと思います。
あとがき
あくまで競プロ用として。