This is a slight tweak of a practice guide I wrote a while ago on USACO reddit since I thought it could be helpful to people here. Some USACO specific sections or extra clutter I left out here that aren't needed for a general audience. This should cover all general cp advice I have so I never have to retype.

# Introduction

This is a post on how I believe is the best method to practice modern day competitive programming based on my experiences. I assume you already have some knowledge and know simple things like binary search and dfs/bfs, but **read the footnote if you are complete beginner** (never code, solved <50 problems, div2 A/B too difficult, grey or stuck low pupil).

First, a quick tl;dr of the practice strategy before a bunch of specifics and explanation:

In short, mostly you only need to use codeforces (no matter what contest you're training for), find a rating range where you can solve around ~30-40% of the time on your own, and just grind down the problem set tab in reverse order of id (the default sorting). Also take part in every live contest you can, and virtual any live contests you miss.

Also, if your primary goal is some goal outside of codeforces (let's say USACO, but could replace with any OI or if ICPC replace instance of OI with ICPC) Approximately once per week (probably on each weekend), I recommend you virtual an OI contest then upsolve the ones you understand the editorial for after. This should be old USACO contests until you finish all in the past 5 or so years, then use OI checklist to find new contests. Make sure you go for subtasks just as you would in real contests when doing so.

Some parts of this method may seem strange to you, so I'll explain in more detail and comment on why I believe it is the best method, and give some proof. If you're too lazy to read all of it, **the most important parts of this article are bolded**. Also, **I am assuming you are able to practice somewhat regularly (at least a few days of practice done each week for multiple months), and this practice is unlikely to work if you don't. However if you really want to improve fast, ideally practice should be daily, no breaks.**

# Goal of Practice

First off, what is the main goal in practicing efficiently? I would argue **you want to come across as many subtle ideas and concepts as quickly as possible and learn to intuitively realize when to apply them.** This is what my practice method is centered around.

Another important goal is **you should also feel discomfort in effort of trying to think new ideas as much as possible, but don't mistake this as time being confused with discomfort having no idea what to do.** Actively making new insights as fast as possible is the state you should be in a lot during live contests and need to endure actively thinking new ideas while trying to not repeat same ideas in your mind. But when you have no clue how to approach/understand a solution to a problem, you are more likely to lose focus and are not helping yourself, so you want to minimize this.

# Why Codeforces?

So, why only codeforces? Well, recent codeforces problems do a decently good job of introducing a large variety of concepts, particularly in the 2000+ rating range. Thanks to the large standards of wanting non-standard problems each contests, many small math tricks and greedy techniques are introduced, along with standard algorithms and data structure appearing decently enough. This is why I think they are the best collection of problems, as opposed to many other judges that are more standard and less diverse or innovative. **Recent codeforces contests are by far better than old contests however, so that is why you should grind down the problems from most to least recent in the problem set tab.** If you have done all contests later than contest 450, you should probably start using another judge and start doing more virtual contests, but at that point you probably don't need this guide.

# How to Approach Problems in Practice

Alright, so codeforces seems good. Why only a rating range where you can solve ~30-40% of the time? Shouldn't you be practicing coming up with solutions on your own? Well, like I said earlier, you want to come across as many concepts as quickly as possible. If you're able to solve ~80%+ of the problems you're doing on your own, even if it takes a while, or in fact especially if it takes a while, you are not using your time most effectively, as you were already able to come up with the concept on your own. **It is OK to read editorials often**, that is where you actually learn new things. **Binary search on the problem set tab to find a rating range of problems that fits the ~30-40% specification, and I recommend the rating range to a few hundred points wide.** You can just shift range upward whenever lower end feels easier and you're solving more.

Well, the next natural question is how long should you take before reading editorials? I will argue **only spend 15m thinking, after that if you're still having ideas keep thinking, but if you're just stuck read the editorial. However, if reading the editorial gives you new ideas continue thinking again.** Sure, you may discover a trick you came up with yourself you can use later after a long time thinking, but was it worth spending 3h coming up with the solution on your own when you could've gone through 2 or 3 more problems if you read the editorial instead. However, going through too hard problems is just as bad is going through too easy problems. It is not worth spending 4h understanding a 3000 rated problem when you could learn much more concepts from 4 2300 rated problems in the same amount of time (if that's good for your skill level). That's why I say ~30-40%, this is usually the point where you can understand the editorial relatively quickly but aren't able to see the concepts on your own. Also, **this is another reason to use codeforces instead of other sources, the problems are shorter so you can get through more faster and it is easier to find many problems of similar skill level**.

Some important notes, however, are to **take the 15m of thinking very seriously and implement every problem**. *This is extremely important!!!***you should only be looking at editorial when you are really out of ideas and trying to think longer will just make you unfocused or reiterate old ideas. In other words you should feel mentally exhausted!!** (or you're not working thinking hard enough). Don't be lazier than you would be in a contest, don't give up because you don't want to think harder on details, don't think/implement leisurely. It is important to practice making observations on your own, and you should be solving problems in the range more and more often as you go down the problem list, that's how you know you're improving. **If you're not improving, you are likely not exhausting yourself thoroughly.** You may think you can get through more concepts earlier without implement too, and this would fit the main goal of practice better, however, it's important to always implement every problem that isn't completely trivial, even if you mind solve it on your own, as you will remember it better and often you will realize you didn't understand the details as well as you thought before implementing. Always implement before reading editorial if you think you have idea, even when not sure, and don't look at others implementation before you solve even if you read editorial except for last resort.

**I also recommend timing yourself when doing problems, at least while implementing.** This will help you stay focused and improve your implement speed (which is important so you don't waste time implementing in contest). If you record your times you should hopefully see yourself getting faster for a fixed problem difficulty :).

**When you finish a problem, make sure you reflect on techniques and mindset used and how you could generalize thought process to solve other problems more efficiently** (imagine you were teaching someone else best way to approach similar problems). Similarly do this when you learn new algorithms or tricks and imagine how you would come up with on your own. Try to come up with your own list similar to one I have in "extra advice how to think" section. Similarly reflect on what can go wrong and how to consciously avoid mental traps. Also, it can be good to look at others solutions after you finish a problem quickly to see if there are any implementation tricks you don't know, and similarly reflect how you could make your code more concise.

# When to Learn Algorithms/Data structures

Next thing to come up is when in this am I supposed to learn new standard algorithms and data structures? I advise **when you come across an algorithm or any other concept (maybe math idea) in an editorial you don't know about to immediately find and read an article about it, implement in the context of this problem, and then continue just moving down the problem set tab.** You can usually find an article on USACO guide, cp-algorithms, or a codeforces blog. The idea behind this is that algorithms should come up at a rate according to their relevance, so if the algorithm really is important you should see it in more problems soon, and you don't need to go looking for more problems with the topic. Similarly, it is important to see algorithms in context, which is why **you should not practice by topic**, as you will likely miss out on many more subtle techniques and tricks not in a topics list and get too used to knowing the algorithm used ahead time when you should be trying to figure that out in the 15m thinking time.

However, if you want a break or have other extra time when you can't do problems, reading through random algorithm articles in the locations listed above is a good way to expose you to some new ideas. But it is still more important to be actively solving problems when you can.

# Live Contests

The number one thing that probably looks wrong with this practice method, despite the reasonings I gave earlier, is that you seem like you are not practicing solving problems on your own often enough. This is where live contests come in. **It is important to take part in as many live contests as possible from** *every***judge you can (except ones where every problem feels too easy)**. This is where you practice thinking on your own, and if you look enough there are tons of contests all the time, particularly high quality ones from atcoder and codeforces. **You should also upsolve the hardest problem you didn't solve during the contest,** however, after that you should just go back to the codeforces problem set grind unless there are more problems from the contest within your practice rating range on codeforces. Lastly, to make sure you're taking enough contest, **take every codeforces contest you miss that would be rated for you as a virtual contest.**

**Also, if your primary objective is some other contest (say USACO/OI but can replace with ICPC), you should do OI virtual about once per week as subtasks are becoming more important in USACO plus probably good to have more extended focus practice anyway.** You also want to shift practice to doing mostly OI virtuals the week before a USACO contest begins. Make sure for these virtuals you are going for maximum points like in a real contest which may mean implementing subtasks, not just implementing full solves (or whatever other contest specific traits that differ from codeforces). If you aren't practicing a ton or you feel virtuals are taking too much time away from doing codeforces practice maybe do every other week instead of every week.

# Scheduling Practice

This is less important but more just some pointers on scheduling time to practice consistently. I think it is obviously best to practice daily, and it isn't as hard as you may think it is if you build up good habits. **I think it is good to have a regularly scheduled time where you can practice each day**, as this makes it more of a consistent habit. Similarly, **if you can set aside a specific location to practice as well that would be good**, as this can give your mindset the habit that a specific time and place is for practicing only, and you build focus**.** **Try to practice at least 90m for your scheduled time**, but preferably longer. And ** get off discord!!!** when you're practicing in the designated time :clown:.

Besides scheduled practice time, you can probably fit in more practice time in some or many days in different ways as well if you are serious. For example, **I think it is good to memorize some problems at the beginning of each day, maybe a bit harder than you'd normally practice, and think about them all day** during school, shower, eating, etc., or maybe the same problems for a few days. This helps you practice thinking more on your own. Also, when you have free time in class or while in car and someone else is driving or something, this is a good time to read algorithm articles. When I went to public school I also bought a portable keyboard to practice in class and spent most school lunch days in the library doing problems, but this might be overkill. **Point is find all times of day to practice any way possible when you can, but most import is the scheduled practice time.**

# Adjustments Closer to Big Contest

If you are training for some main goal (hopefully for the past several months at least, following above methods), **when you are within a few weeks away of big contest, start spending more practice time on vc's for that contest, and look over the syllabus/relevant ideas for that contest if list exists**. Also consider if you are in these pitfalls:

You are too slow at working out ideas or implementation => do more fast-paced contest vc's, time yourself in other practice.

You are bad at allocating time in OI/ICPC style => focus on more relevant vc's and practice subtask allocation, figuring out which problems to work on, and when to move on like in real contest.

Still not able to make big insights that seem to come out of nowhere => try more guessing and some atcoder lol.

# Outro

Hopefully this was somewhat useful to some of you, and gives you a comprehensive guide on how to practice for USACO and competitive programming in general. **Please share this with others if you think it is useful.**

For any more experienced people, let me know if there is anything you strongly disagree with what I said, I'd be interested to hear your viewpoint, though you're unlikely to change my mind :).

# Footnotes

**I recommend the beginning of the usaco training page to *complete beginners*. I think it is a good way to start out as it guides you on the basics, and you should be able to start as soon as you know the very basics to a programming language, preferably c++ (you can use codeacademy to learn basics, it should take only a couple days max. you learn other parts about the language as you solve more problems and googling as needed). However, as soon as you finish chapter 1 or the problems feel easy (or if codeforces is still too intimidating maybe hard max finish chapter 2), that is when I recommend you start using this practice method, and perhaps also try some problems from the cses sorting and searching section. However most people reading this should already have some experience.

Sources mentioned:

USACO — http://www.usaco.org

Codeforces — https://codeforces.com

Atcoder — https://atcoder.jp

CSES — https://cses.fi/problemset/

Training gate — https://usaco.training

OI Checklist — https://oichecklist.pythonanywhere.com

Cp-Algorithms — https://cp-algorithms.com

USACO Guide — https://usaco.guide

Codeacademy — https://www.codecademy.com/catalog/language/c-plus-plus

# Extra Advice How to Think to Solve Problems

**Overall, just make sure you are always thinking new ideas and repeatedly combining old observations to make new ones. Don't worry about solving all at once, just think one small step at a time!** Usually this means think what do you know for sure, then use to guess ideas on properties and direction and check if you can prove, combine your previous observations, then repeat. When really stuck, guess more extreme (it is another thing people who aren't improving don't do enough). Actually write down you're observations and make sure you're writing new things as fast as possible, even when seems small or irrelevant. But for some more direct tips, try going through the following checklist when approaching a problem:

- look at everything from perspective of binary (both bit representation and splitting things in halves) and graph (pairs in input), or sometimes as geometry coordinates
- think how information you have can be reused (like dp but more general, eg 2ptr or extending construction, sweepline), ask what is dependent and how, order by dependency. also try making one choice then and get same problem then induct (eg greedy, mst, dp, decision tree like trie, ask "what do i know for sure"), or combine smaller problems to get answer (eg range dp, d&q, mitm), so can reuse info of smaller problem.
- reduce things to as simple as possible, compact representation of info, get rid of redundant transitions/states/etc. what is minimum needed for condition to be true? when something changes or decision made what is minimum that actually matters? sometimes combine operations into simpler one (eg try turning operation into something can binary exponentiate). bound everything as tight as possible and use to reduce states to consider. is answer/construction equivalent to bounds/minimum conditions (guess when stuck)?
- make formulas out of everything, expand/rewrite as many ways possible (even simple like |x| -> +-x). think about related formulas to transform (eg combo) and other representations (don't forget matrix/polynomial).
- visualize everything, draw things out
- look for structures like montonicity, concavity, etc. (eg bsearch/dp opt) along with new conditions/constraints implied (eg sqrtn distinct of n total), and do this for every part of problem, whether specific part or entire structure of solution
- go through testcases by hand (both initially with brute force and with your current best ideas), maybe also make generator/brute force checker if stuck to further look for patterns.
- don't think same things over and over, write down everything you think and try to always write down new ideas, every small new observation is progress and may be able to be combined with other ideas eventually, but rethinking same things will not help
- think of simplified cases then extend/reduce to them (reduce a[i] = 0/1, array->tree->graph, 2^x->k) or imagine assuming something you wish exists already exists (like data structure, constraint eg for bsearch, previous knowledge, etc.) and solving from there, chances are thing then does exist if helps
- reverse/change ordering of process (eg change order to simpler like change general add/delete to add/[delete most recent op] offline) or look at inverse (especially for counting) or just view problem in different way in general, restate problem/conditions in as many different ways as you can to get new perspectives. nice transformation usually means right direction (eg difference array).
- if something reminds you of standard algorithm, or you find too slow solution for some part, think of every way you know how to do that standard thing and see if any modification relates to what you are doing, and think deeply what parts can be changed for specific problem
- if something seems random in statement like any abnormal constraint or is similar to known problem but different in some way, is probably key to solving so consider why it is put in statement
- don't forget sometimes can brute force small choices or if too many choices can pick random one or something that stands out (like max/min, only closest on left/right, etc.), extremals is often key. think carefully and guess what not matter if problem seems too hard initially. in constructive/interactive with many options can likely solve with only small subset of options.
- don't overcomplicate. try multiple directions, if too many steps or edge cases probably not right direction. almost always a nice easily provable solution. guess nice things (eg simplest greedy/construction), hope they work, then check but don't get stuck forcing path. take step back when clowning on small details even if you know it is right general direction
- try focusing on answer for one element at time instead of entire process (like in counting or creating bsearch condition, local easier to update for queries), or sometimes opposite (eg graph out all solutions, know ahead of time offline). in general change scope of thinking
- believe you can solve every problem, but also treat every problem as a challenge that you take one step at a time. even most standard ideas you can learn on your own if you treat same way as any other problem
- if something you remember very vaguely seems similar but you don't remember source and barely remember details, don't waste time trying to remember old thing, just start resolving from scratch
- as stated by Perpetually_Purple in comment below, sometimes can try to cheese with random/heuristic if running out of time. especially true for OI contests with subtasks
- sometimes can split problem into parts which can be solved differently based on constraints (eg sqrt decomp, small to large, upd and qry compute different parts, even/odd).
- also break into independent problems (eg intervals that don't affect each other, solve x and y coordinate separately). when dependent on multiple things, process in order that gets rid of thinking about one and only worry about others (eg sweep one dimension, query other).
- map things to a canonical form (eg lexographically minimal) or map representations that are equivalent to help with counting or alternate way to view solution. (eg think of greedy idea to get specific configuration then have counting dp mimic the greedy method to not overcount, find simple idea for single query then speed up multiple queries by precomputing conditions when add during greedy to speed up).
- imagine assuming you know solution ahead of time and analyze or fix choices ahead of time and solve rest, can use this to prove things equivalent, choices not to consider, or properties of optimal configuration.
- try only computing minimum necessary at each point of time, especially for update/query. can sometimes use amortized/lazy arguments (eg keep track of covered intervals in set, lazy prop on segtree).
- ask what stays the same and what changes. how does a single operation affect properties of a problem (sum/difference of elements, always progress towards goal, reversable, etc.)? when doing testcases by hand guess these types of things then prove/disprove. use these properties to prove things like which choices are optimal or what is bottleneck to bound on answer.
- Similar to 3 and 10, try compressing groups of things and solve over those group when relations within them are irrelevant, and keep updating when you can simplify further throughout process (eg compress cycles, scc, biconnected components, directed mst).'
- When guessing idea, make sure you are listing through all assumptions being made and that those assumptions you know for sure hold true and completely encompass the problem. Also make samples around idea of what you think could go wrong, and use that to help you prove or disprove idea. If you're taking too long disproving wrong ideas, you likely need to go more one step at a time, don't guess extreme until more stuck.
- If stuck working out details when have main idea, work out more testcases by hand and/or write detailed pseudocode and find what steps you are not entirely sure what they work and think harder. Don't be lazy about writing details!

Also it is good to use problem constraints to guide your initial direction of thinking, but don't let it constrain you to specific ideas. And whatever you do **don't misread the problem**, better to spend slightly longer reading and understanding correctly than solve wrong thing.

# Implementation Tips

**First check briefly that you are not missing easier idea/method to implement.** That will save most time.

Try to have clear idea of each segment of code you will write, then write as fast as possible. Sometimes you don't have clear idea of entire code you write and only general outline, and that's ok, but in your mind have different parts of code in small chunks and have each small chunk planned out clearly before you write then think if needed before writing next part. **Try to keep plan your code to be as concise as possible while still easily readable and make it where you are not rewriting same thing multiple times. If you keep rewriting, you need to step back and plan out better, check your ideas.**

Also for debugging, just make a bunch of print statements in code and look for problems. Try to binary search and figure out where in the code the outputs are first not what you'd expect. If you realize some part is not right, **don't get stuck making small edits trying to fix, go back to planning and rewrite when clear.** Also try working through some examples by hand following steps of code, and read through every single line of code. It is likely the mistake is somewhere where you were sure you couldn't mess up lol.

Also adding one sentence comment to code on main idea of every problem might be nice if you ever need to refer back.

# Allocating Time in OI Contest

I'm assuming 3 problems in 4 hours (adjust scale as needed). **I usually read all 3 problems in first 15 minutes, then spend about 15 minutes each to think about each problem and decide order of difficulty I find easiest. If I fully mind solve one in that time I immediately implement, otherwise I do as follows. I then try to divide the next three hours to be roughly even among the three problems, and try the problems in order from easiest to hardest.**

**While focusing on a problem, it is very important to stay focused on only that problem.** For most of hour on problem should implement as soon as you full solve but only implement subtasks to test ideas, if you think it help you towards full solution, or you are completely out of new ideas (in which case move on after implementing subtask if u still don't have new ideas). However, **if you already use up ~50min for that problem and still don't know full solution and won't reach in next 5min, even if you think you could make more progress, just implement what subtasks you know and move on.** It is important to actually move on as you may have wrongly assessed which problem was easiest so you want to have time to try all the problems (this has been my downfall multiple times in past). This means once you move on don't have more lingering thoughts usually and fully focus on next problem.

# Math + CS Practice

If you are practicing math olympiad and cs olympiad, or just want some reading material that might help you, try reading some of and doing some problems from this combo book. Overall it will be better for you to just do be actively solving more problems for cp practice, but if you have some other free time it is a pretty good read and cp is basically olympiad combo + data structures + implementation anyway.

Practicing for math olympiad in general will also help you with competitive programming, but if you are only focusing on cp it is better to just work on cp problems.

# Extra Motivation

**In everything in life, the key to success is learning to find fulfillment in every small step you make towards progress.** Related to cp, every problem solved and every day of practice is one step closer to your competitive programming goals. When solving a problem every new observation is one step closer to finding the solution.

**Also, make sure you know your priorities and what you really want out of life, don't have regrets.** If you really want to be good in cp, stop wasting time, stop taking days off, start solving problems as much as you can and you will find success. Obsess over what you want most until you achieve it.

I forgot to mention you should orz codetiger927 for best results and +200 rating points.

codetiger orz

codetiger orz

codetiger orz

codetiger orz

What means orz?

Need more these type of blogs rather than those spam blogs. Thanks

I don't disagree

Who asked?

Although I don't agree with 15 rule, the rest of it seems great. One more specific advice I'd like to give is many times randomised/heuristic solutions work with great probability (especially but not limited to constructives ), it's a quite powerful tool and you can use it to cheese quite some problems.

Could you explain why you don't agree with the rule?

Because I'd like to think more

Fair enough. I think the rule should vary depending on your skill level. For noobs like me, we aren't aware of as many approaches to problems as more experienced coders. In my opinion, the higher your skill level, the more time you should give yourself to think.

personally i dont think it depends on skill level, i still on average think for similar times (before i skip the problem) as when i practiced on 2100 problems — probably just depends on the person and how long they will have fun for before stopping.

That combo book is very based.

Helpful++

How many problems typically needed to grind in each rating range in your practice method?

Idk, depends on person, maybe 30-60 per rating? Just move up the lower end of range whenever easier end begins feeling boring and you're solving more.

Also you will move up lower ratings much faster than higher ratings.

I'm preparing for interviews and online assessments for big tech companies. Unfortunately, in India, I have heard leetcode is not enough and problems generally asked in interviews are of hard cateogary (according to LC). So I was thinking of only solved binary search, graphs, DP tagged problems on codeforces as I think Constructive, ad-hoc problems are rarely asked in interviews? What do you think?

I have not researched much about interview prep, but I would just focus on first consistently solving leetcode hard before anything else if all you want is just to pass interview. You should be practicing problems for the type of thing working towards, and leetcode already has only problems for interviews which is different from competitive programming. You can still use same method described but with leetcode though.

If you really think leetcode problems are not enough for interview as they are more like competitive programming (I doubt), or want extra work to learn how to think more generally, then I would do codeforces and not sort by any category as described.

Thanks for the post. I will become master in 2 months and make you proud.

:)

lol nice one

It's 4 months... (:

its been 5 months bro

Nice

HELPFUL. THANKS

camper orz

sakurajima > katou

If you realized katou supremacy you would be gm by now.

orz

What do you mean by "generator/brute force checker" in line 7 of

Extra Advice How to Think to Solve Problems?generator = make code to generate your own testcases for problem, usually don't want too large

brute force checker = make slow solution code

Using these, you can see if there is pattern in solution based on input you didn't otherwise notice by running many cases and see if there is correlation with input. It is also good for debugging code to find case that gives wa.

in a contest, absolutely, this is a great idea and can lead to solutions often.

But when practising, shouldn't one try to solve the problem through deductions? problems are rarely solvable by such bruteforces. I do not mean that one shouldn't practise it however, just that you should try to solve without it afterwards atleast.

I don't think you need to solve any different in contest and in practice, and if you don't ever try in practice maybe you know less when to in contest

~~but I am usually too lazy to do when practicing~~. However, tho it is more commonly useful in OI, it has helped me solve a decent number of problems. But I usually use it only if I seem to not be making progress through solely deductions.I should say this book can teach you how you can prove your solutions using mathematical means. I think that proving your approach is very helpful in developing an intuitive understanding.

will only solving codeforces problems cover my icpc preparation too?will I be covered the standard algos that appear in icpcS? For example , how am I gonna learn HLD ,grundy etc. ? Isn't probability of them appearing in cf problmset very very low? So isn't combining cses a bit a good option ? SuperJ6

Learning good thinking mindset is more important to success I think, and for regional contests in my experience majority of harder algorithm application is relatively straight forward and while more critical problems are more dependent on cf-like thinking (but it might depend on region).

However, ICPC has never been a focus of mine, so it is thing I have least solid advice. If you think spending a little bit of time making sure you know most common standard algorithms for icpc with cses or maybe better is filter problemset by icpc contests sometimes on codeforces that might be reasonable. However, I think for most part doing virtual icpc weekly/biweekly will expose you to enough, and once you get to a bit higher rated problems on codeforces you will see such techniques more anyway.

I cannot agree that recent contests are far better. Well, maybe it is the case for 2000+ rated people. But for 1500-rated I'd recommend to solve the oldest problems since they contain must-know ideas you never encounter in today's problems. And archives (there is a good archive, a copy of former acm.sgu.ru, right here).

I know that this is probably a stupid question, but i'm kinda new and stupid, so by rating do you mean problemset or something else? and if something else, how do I find the something else?

You said

"You should also upsolve the hardest problem you didn't solve during the contest"It sounds like if I participated in Div1 and solved A and B, I should upsolve problem F?

Did you actually mean

the easiest problem you didn't solve?gonna grind now let's see how far i can go (current rating 0)