Template I developed while moving from CM to Master
I feel quite proud of the template I built up while gaining several hundred rating points earlier this year, so I'm sharing it here. I'll organize this post as follows: 1. Links to the template 2. Demos of specific cool tricks that the template allows 3. Why a good template is important, aka what a good template can (and can't) do for you
I hope the code is readable enough so people can steal just a few of my tricks if that's what seems useful to them. Also very interested in feedback or suggestions about how to make the template more useful! Links to the template
Here are github links to the version as of 2022-08-19 and the current version.
In case someone prefers to see it within Codeforces...
Cool tricks in the template
Pretty debug printouts
Demo
Here's some sample code: ~~~~~ void solve() { ll a = 14; double b = -3e-2; char c = '@'; string s = "Test String"; vector q = {1, 6, 4, 3, 5, 3, 1}; dbg(a, b, c, "", s, q); dbgc("show this on left", make_pair(a, c)); // dbgc = "debug with 1st arg as comment" dbgcP("diff colors", a, b); // uppercase letters change the color; all terminal colors are available dbgc("expressions work too", 2*b, gcd(a, a+4)); el; // empty line
// complex/nested data structures work too. map<pair<ll,ll>, V<string>> dat = { {{3, 5}, {"abc", "def"}}, {{4, -1}, {"apple", "peach", "banana"}}, {{-5, 0}, {"tourist", "jiangly", "um_nik", "slime", "ksun48"}} }; dbgY(dat); // that may be pretty messy to read all on one line though, so we can use: dbg(pdh(dat)); el; // show how "regular output" lines look visibly different from dbg() lines. cout << a << ' ' << b << ' ' << c << '\n'; // what if we have a big object and we want to "get the idea" of its contents // without printing the whole thing? vector<pll> vbig; FOR(k, 0, 100) {vbig.emplace_back(k, -k*k);} dbgR(pdh(vbig, 10)); // short for "print_details_helper" el; // Advanced: pdhf lets me specify a function, so f(x) will be printed for each x in the structure. dbg(pdhf(vbig, [&](auto x){return x.second;}, 10)); // pdhf = "print_details_helper_func" dbgcBold("done!"); return;
} ~~~~~ ...and here's a screenshot of the output:
Summary of key features:
dbg(a, b, c)
prints line number, exact text you passed in, and the values of all those variables/expressions/objects. Optionaldbgc
version uses the first argument as a marker or comment, which is placed to the left. All printouts are indented to keep them visually separate from the normal outputs to cout.- Different color options so you can easily see which printouts came from which dbg() call. Default color is cyan; specify other colors with dbgP (purple), dbgY (yellow), and so on. All the ANSI terminal colors are provided except black; see the template code for the full list.
- Handles pairs, tuples, and STL data structures including arbitrary nesting.
- All dbg() stuff is removed at preprocessor stage if we didn't pass flag -DDCCLYDE_LOCAL when compiling. That means I don't need to bother commenting out these lines before submitting to online judges. (Regular cerr printouts won't cause WA, but they could easily cause TLE.)
- pdh ("print details helper") functionality prints one entry per line; useful if we're printing a complex object since printing on one line can be hard to visually process.
Realistic example
The demo above may make it seem like the different colors are just visually noisy instead of useful. Here's an example of how I'd use them in "real life" on a simple problem.
This is my (IMO) heavily improved version of ideas stolen from tourist and tantam75, see blog.
"Unhackable" and faster unordered_map and unordered_set replacements
unordered_map
and unordered_set
are notoriously hackable; see classic blog post. Also, they are usually around 5x slower than the alternative gp_hash_table
, see another blog. My template defines replacements umap
and uset
which just implement the recommendations from those posts. My versions also happily hash arbitrary pairs, tuples, or iterable STL objects. Caveat: pairs and tuples have worked fine for me, but hashing more complex stuff like std::vector
s often leads to.
I/O shortcuts
Precompiled headers
TODO TODO TODO
What a good template can/can't do for you
I've seen threads where people argue that a good coder shouldn't rely on a long template. I think it's totally fine to think that, and many strong coders use a short template or no template. By comparison, I think it's very very hard to reach high ratings without a library of data structures / algorithms you can quickly paste in or modify.
The main things I think a template helps with are 1. Reduce repetitive typing: save 1-5 minutes on each problem by using small prewritten functions/macros for I/O, binary searches, etc. This can also make it a little easier to code correctly, since it's no longer possible to have typos in those functions. 2. Make debugging faster and easier: Using default C++, it can be easy to make mistakes that
This year, I moved from around 1850 "true rating" (i.e. if I did a bunch of contests at that skill level, I think I'd end up around 1850) to Master level. In my most recent practice+rated contests I was ty
Earlier this year, I was around 1850 "true rating" after having been around 2000 "true rating" in 2017-2018. That felt bad because
Questions, suggestions, advice?
I'm very interested to hear to advice about how to accomplish the same things in a better way, or feature requests that would make the template features nicer to use, or even just random questions about why I did things a certain way. Some of the "weird" decisions are made on purpose to get around non-obvious issues that I didn't cover in this blog, and others may be just because I'm clumsy with some of the tools I'm using here, so even asking "silly" questions can be useful — either I'll explain something you didn't see, or I'll learn something from your idea about how it should have been coded instead.