Hello there, I would like to share my personal experience on how I reached expert. Some people asked me regarding this so I decided to write a blog.
Firstly, I am incredibly thankful to my friend an1ket_62 for introducing me to Codeforces. It has been a real game-changer in improving my competitive programming skills.
Sure thing! When you ask someone how to get better at something, like CP, they usually say, "Just solve lots of problems," and that's absolutely right. But I've observed and talked to many people who practice, including myself, and I can offer a bit more insight. If you truly want to excel and improve, thoughts of practicing regularly will keep popping in your mind. If you don't feel like solving problems or you only want to do it once a month, you should ask yourself how much you really want to get better.
For example, imagine you want to become a better basketball player. If you truly want to improve, you'll feel excited to shoot hoops whenever you can, even if it's just for a few minutes each day. But if you only want to play basketball once a week and don't enjoy it the rest of the time, it's worth thinking about how serious you are about getting better at the game. Your enthusiasm and commitment are keys to improvement.
What I want to convey is that if you really have a strong desire to improve your skills, you will definitely love to solve problems whenever they come to mind. Whether it's during your free time or even for a few minutes a day, you'll be motivated to think of some problem.
How to select Problems ?
Imagine you have a list of problems to solve, like math problems or graph/tree problems. You decide to pick problems that match your skill level and the topics you want to improve in. So, you're only choosing problems that are just right for you.
Here's the issue: When you start working on these problems, you tend to solve the ones that are easy for you. The ones that seem a bit tough, you often ignore or keep switching them until you find one that's not too hard.
Now, let's say you've solved more than 60 problems with a certain difficulty level, like a 1500 rating. But ask yourself – are these 60 problems really a fair representation of all problems with that rating? Or are they mostly problems you found easier because they were related to stuff you already know?
The key issue is that those 60 problems you've solved, were problems you found easy and were already related to topics you're familiar with. So, these problems don't truly represent a random selection of problems with that difficulty rating. They are skewed towards what you already know, which can give you a misleading impression of your abilities.
How to approach any problem ?
First assume that you are solving a problem that you don’t yet know how to solve, but you come possible up with the solution, maybe using a lot of time.
- If you know the input constraints and the upper limit for execution time, you can quickly discard many types of algorithms that won't work within the given time limit. N is below 20? You're probably looking for that O(N * 2^N) dynamic programming solution. N can be up to 1M? You have to write an algorithm with average complexity of O(N). Another problem that requires a data structure heavy approach where you have to squeeze your naive O(N^2) solution into O(N log N).
- If you just proved to yourself that the problem is impossible to solve (for example it's near-trivially reducible to some well-known NP-hard problem), reread the problem statement immediately. Most probably, you misread/forgot some key element. Maybe the graph has some special property. Maybe the elements of the array are unique. Maybe there's some sentence of the statement that could be interpreted in a different way.
- Try to remember some similar problems that you had to solve. Quite many problems do not have a brand new idea. So probably, you can use your experience of solving a similar problem to solve this one.
- Let's say that you've found the solution for the problem (hurray!). Let's consider some particular case of a problem. Of course, you can apply the algorithm/solution to it. That's why, in order to solve a general problem, you need to solve all of its specific cases. Try solving some (or multiple) specific cases and then try and generalize them to the solution of the main problem. Such specific cases can be regarded as the simplifications of the problem, i.e. we can reason by the following principle: "if I don't know how to solve a complex problem, I think I'll simplify it and find the solutions of the simplified version". Think of it like this: if you're trying to bake a fancy cake, but you're not sure how, you might first learn to make a simple cupcake. Then, you figure out how to make frosting. Finally, you combine your cupcake and frosting skills to make the delicious cake you wanted.
- Try to process some small samples on your own. If the problem is about a game, play it. Sometimes try to visualize a process or a model for better understanding. It's a little like how movies show the way scientists think. Try to think in images, imagine the solution, see it unfolding.
Proving your solutions
Actually proving your solution doesn't mean that you always have to come up with the proof which seems to be overly rigorous and difficult. You don't ever need extensive proofs in competitive programming like you needed in maths. The easiest way to improve in Competitive Programming is the art of developing intuition of something you can't quite intuit anything about. Sometimes you might struggle in easy problems because you have not developed proper intuition. When you say you enjoy easier problems that you initially struggle with, it means that these problems are like training exercises. They help you build that "gut feeling" or intuition for solving similar, more challenging problems in the future.
While proving your solution, think of every step you took while proving. If you wanted to justify to an opponent you were correct, what would the opponent try to argue against. If you think you can't justify your reasoning over his to a jury without reasonable doubt, your proof needs to be more specific.
Imagine you're in a debate with someone who wants to prove you wrong. They'll look at every step you took in your proof and try to find mistakes. So, you should think like your opponent and ask yourself, "If I had to explain to a group of people why I'm right, could I do it in a way that leaves no doubt?"
If you're not confident that you could convince a jury that your proof is correct without any reasonable doubt, then your proof might need more details and explanations to make it stronger. It's like making sure you have all the evidence you need to win an argument convincingly.
Some additional things
- Have 1 or 2 good friends with whom you can discuss things and outperform them.
- Do not solve too easy problems. Solving very easy problems won't improve you. Also, you should solve on the topics you are weak on and solve randomly(random solving problems a little bit higher than your rating is one of the best practicing techniques!)
- Upsolve.
- Don't underestimate Binary search.
- Read the editorial if you are not able to get anything.