Блог пользователя antonkasko

Автор antonkasko, история, 19 месяцев назад, По-русски

Все мы хотим писать код быстрее и проще, особенно на соревнованиях, когда от времени отправки решения зависит место в таблице. Я собрал небольшой шаблон для соревнований по спортивному программированию.

Шаблон

Что тут есть?

Ввод/вывод

Несколько строк которые обычно всегда ускоряют ввод/вывод (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
  • Проголосовать: нравится
  • -7
  • Проголосовать: не нравится

»
19 месяцев назад, # |
  Проголосовать: нравится +15 Проголосовать: не нравится

Не вижу шаблона для поиска гамильтонова пути в графе за $$$O(n)$$$, поэтому дизлайк.

  • »
    »
    19 месяцев назад, # ^ |
      Проголосовать: нравится +4 Проголосовать: не нравится

    Ещё очень хочется линейное дерево Гомори-Ху, но его тоже нет( Прошу автора как можно скорее исправить этот недостаток.

»
19 месяцев назад, # |
  Проголосовать: нравится +30 Проголосовать: не нравится

Постараюсь не говорить об объёме и полноте шаблона, как по мне, каждый просто записывает в шаблон то, что ему пригождается, и у каждого шаблон появляется самостоятельно. Тем не менее, раз этот стал выложено в общий доступ, то я чутка покритикую (прошу прощения за объём, мне просто стало интересно, сколько я смогу наскрести, тут есть и довольно бесполезные придирки, но большинство пунктов я считаю существенными):

  • Между #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.

Что произойдёт
  • Довольно желательно добавить const перед типом переменной в операторе вывода, чтобы показать компилятору, что эта функция не меняет пару или вектор. Если вы пишете что-то такое void function(const vector<int> &v), то это вообще необходимо, вдруг вы захотите вывести v изнутри функции — просто не подойдёт тип, текущий оператор вывода принимает только неконстантные объекты. Ну, а если не пишете, то, наверно, ничего не сломается, но вообще писать const неизменяющимся переменным — хорошая практика контроля себя.

  • Довольно желательно, чтобы вывода использовал не cout, а out, переданный в качестве аргумента. Если вы всё время при выводе пишете cout << ..., то это эквивалентно, но к вашему удивлению, запись cerr << v также выведет v в стандартный поток вывода, в stdout, а отнюдь не в stderr. Ну, и, разумеется, это будет вести себя неожиданно, если вы используете ifstream при работе с файлами, и пытаетесь вызвать оператор вывода у ifstream. Всё это касается и cin.

»
19 месяцев назад, # |
  Проголосовать: нравится +13 Проголосовать: не нравится

В C++20 завезли <ranges>, и теперь макрос #define all(x) (x).begin(),(x).end() не нужен, поскольку можно просто написать std::ranges::sort(x) (вместо std::sort(all(x))).

Да, и из-за отсутствия скобок макросы range и rrange забагованы:

Баг
»
19 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

cout.tie(0)

)))))))))))

»
7 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Автокомментарий: текст был обновлен пользователем antonkasko (предыдущая версия, новая версия, сравнить).

»
6 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Автокомментарий: текст был обновлен пользователем antonkasko (предыдущая версия, новая версия, сравнить).