Все мы хотим писать код быстрее и проще, особенно на соревнованиях, когда от времени отправки решения зависит место в таблице. Я собрал небольшой шаблон для соревнований по спортивному программированию.
Что тут есть?
Ввод/вывод
Несколько строк которые обычно всегда ускоряют ввод/вывод (cout.tie(0) ничего не делает):
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
С помощью этих строк, можно выводить и считывать вектора и пары, с помощью стандартных операторов:
template<typename T>istream& operator >>(istream& in, vector<T>& a) { range(i, a.size()) in >> a[i]; return in; }
template<typename T>ostream& operator <<(ostream& out, const vector<T>& a) { range(i, a.size()) out << a[i] << ' '; return out; }
template<typename T1, typename T2>istream& operator >>(istream& in, pair<T1, T2>& p) { in >> p.first >> p.second; return in; }
template<typename T1, typename T2>ostream& operator <<(ostream& out, const pair<T1, T2>& p) { out << p.first << ' ' << p.second; return out; }
Теперь можно просто делать вот так (Напомню вместо int можно использовать что угодно):
vector<int> a(n);
cin >> a;
cout << a;
pair<int,int> p;
cin >> p;
cout << p;
Дефайны
Один из самых полезных дефайнов:
#define all(x) x.begin(),x.end()
Теперь можно использовать:
sort(all(x))
Вместо
sort(x.begin(),x.end())
Дефайн специально для раундов КФ, умеет запускать несколько тестов:
#define CF(x) int x;cin >> x;while(x--)
Теперь можно делать так:
CF(___) {
//код
}
Немного упрощений для циклов:
#define range(i,n) for (int i=0;i<n;++i)
#define range(i, s, f) for (int i=(s);i<int(f);++i)
#define rrange(i,n) for (int i=n-1;i>=0;--i)
Этот дефайн ускорит ваш код, если вы часто используете модули. mod — глобальная переменная.
#define md(x) if (x>=mod) x%=mod









Не вижу шаблона для поиска гамильтонова пути в графе за $$$O(n)$$$, поэтому дизлайк.
Ещё очень хочется линейное дерево Гомори-Ху, но его тоже нет( Прошу автора как можно скорее исправить этот недостаток.
Постараюсь не говорить об объёме и полноте шаблона, как по мне, каждый просто записывает в шаблон то, что ему пригождается, и у каждого шаблон появляется самостоятельно. Тем не менее, раз этот стал выложено в общий доступ, то я чутка покритикую (прошу прощения за объём, мне просто стало интересно, сколько я смогу наскрести, тут есть и довольно бесполезные придирки, но большинство пунктов я считаю существенными):
Между
#includeи угловыми скобками хочется всегда либо пробел, либо его отсутствие. Видимо, по какому-то стандарту форматирования лучше пробел.Кажется, раз уж шаблон, то лучше подключить либо все-все полезные инклюды, либо
<bits/stdc++.h>, если он у вас есть. Я подключаю его, и уж не помню, что есть полезного, но, видимо, как минимум<cmath>забыт.Просто упомяну, что
cout.tie(0);ничего не делает, подтверждение, но, разумеется, его можно писать, это не будет хуже, а может вам даже будет спокойнее, что вы не выкинули полезную строчку вместо бесполезной.В
#define, если уж вы их пишете, аргумент надо заключать в круглые скобки — вот так:#define range(i, n) for (int (i) = 0; (i) < (n); ++(i)), потому что#define— это команда препроцессору произвести замену в вашем коде, препроцессор практически ничего не знает про синтаксис. Я не могу придумать адекватный пример, почемуallможет от этого сломаться, ноrangeбезусловно их требует (и вообще, хорошая практикане писать дефайныв любом дефайне оборачивать аргумент в скобки), потому что если кто-то напишетrange(i, x ^ y), то внезапно, после подстановки получитсяfor (int i = 0; i < x ^ y; ++i), что эквивалентноfor (int i = 0; (i < x) ^ y; ++i), а вы, наверно, хотели не этого. Конечно, у^вообще приоритет неудачный, но в записиrange(...)вы с меньшей вероятностью найдёте ошибку, чем в записиfor (...)— в последней фрагментi < x ^ yхотя бы перед глазами.Ещё о дефайнах: раз уж у вас цикл обязательно на
intах, то озаботьтесь написать не простоn, а(int)n. Иначе вас постигнет неприятное, когда вы напишетеrrange(i, a.size()для пустогоa.a.size()имеет беззнаковый (unsigned) типsize_t, при вычитании 1 (типаint) оба аргумента приведутся к типуsize_t, результат тоже будет беззнаковый, поэтому получится ни больше ни меньше, как $$$2^{64}-1$$$, цикл в итоге будет бесконечным, так какint iвсегда меньше этого заоблачного значения.Довольно желательно добавить
constперед типом переменной в операторе вывода, чтобы показать компилятору, что эта функция не меняет пару или вектор. Если вы пишете что-то такоеvoid function(const vector<int> &v), то это вообще необходимо, вдруг вы захотите вывестиvизнутри функции — просто не подойдёт тип, текущий оператор вывода принимает только неконстантные объекты. Ну, а если не пишете, то, наверно, ничего не сломается, но вообще писатьconstнеизменяющимся переменным — хорошая практика контроля себя.Довольно желательно, чтобы вывода использовал не
cout, аout, переданный в качестве аргумента. Если вы всё время при выводе пишетеcout << ..., то это эквивалентно, но к вашему удивлению, записьcerr << vтакже выведетvв стандартный поток вывода, вstdout, а отнюдь не вstderr. Ну, и, разумеется, это будет вести себя неожиданно, если вы используетеifstreamпри работе с файлами, и пытаетесь вызвать оператор вывода уifstream. Всё это касается иcin.В C++20 завезли
<ranges>, и теперь макрос#define all(x) (x).begin(),(x).end()не нужен, поскольку можно просто написатьstd::ranges::sort(x)(вместоstd::sort(all(x))).Да, и из-за отсутствия скобок макросы
rangeиrrangeзабагованы:cout.tie(0))))))))))))
Автокомментарий: текст был обновлен пользователем antonkasko (предыдущая версия, новая версия, сравнить).
Автокомментарий: текст был обновлен пользователем antonkasko (предыдущая версия, новая версия, сравнить).