Please read the new rule regarding the restriction on the use of AI tools. ×

purplesyringa's blog

By purplesyringa, history, 2 hours ago, In English

When I was a child, I knew software development well (though not much of C++), and my parents motivated me to try out competitive programming.

The first thing I tried was dkirienko's section. In the first 20 minutes, GCD and the Euclidian algorithm were explained, the complexity of the Euclidian algorithm was proven, and that was pretty much it. We were then asked to solve a problem set on Codeforces individually. I didn't understand much from the complexity proof, couldn't solve a single problem, failed to figure out what I was supposed to do, and left crying. So yeah, stuff like that doesn't work.

I understood simpler topics, though. I knew basic math, like how to solve linear systems and quadratic equations, and could make simple observations, so the school stage of ROI was quite easy to get through. (The hardest part was to explain to my then-informatics teacher that yes, I want the adult problems.) During the municipal stage, I had 3 hours to solve what I'd classify as a 5-task Div 3 contest. I solved the first three and stumbled on D2B and D2C. That was still a good result for my age, so I was invited to a Moscow training camp.

My experience at the camp was a bit haphazard. I didn't understand the relative complexity of the topics. Which group was I supposed to join? Was it linear and stack algorithms, segment trees, or HLD? I knew what a stack is, I wrote a stack-based parser a month prior. With some help, I figured out I should join the former group anyway.

That day, I was taught how prefix sums work, two pointers, and some stack tricks in 1.5 hours. During this time, we discussed several problems, solved them together with other students (there were about two dozen of us), explained stuff to each other, and took notes. We then spent two or three hours solving problems individually. I didn't understand all the information, but I could apply some of it to the problems. That worked.


I don't want to compare the two groups; I'm pretty sure they all had their highs and lows. I want to compare the experiences.

The way we teach newcomers at Codeforces is closer to my first experience. We tell people to solve more problems, and our only advice when that doesn't work is to read editorials. When the problems require algorithms, we tell them to read an article or two on binary search, and then come back.

Respectfully, you are all morons.

This is not how you teach competitive programming.

What got me from crying at hearing "competitive programming" to loving it was the exact opposite of your advice.

  • I did not focus on ideas, I focused on algorithms.
  • I did not try to solve a problem and then read the editorial when I failed, it was the opposite in 50% of cases.
  • I did not go from idea-based problems to algorithmic problems as I obtained skill, it was vice versa.
  • "Go solve more problems" only helped me when I had high skill, not low skill.

I hope I've explained these points below.

Start with algorithms, not ideas

Algorithms and data structures have substance. They are concrete, finished products. Compared to ideas, their limited scope:

  • Makes them easier to teach, because you only have to convey a particular approach rather than a widely generalized notion,
  • Makes them easier to learn, because all people have very similar views on what the topic is, so you can find a source that works best for you without worrying about losing something precious,
  • Helps the teacher and the student connect because it is very clear whether both are on the same page.

Oh, but wouldn't the student not learn anything and globally applicable useful from this? That's not how it works. Your goal as a teacher is to explain the intuition rather than the algorithm itself. Instead of explaining the "what", explain the "why". If you do that, the little tricks you use to build the intuition and the intuition itself will transfer to other areas.

For example, suppose you need to give an online or an offline lecture on segment trees. You start like this:

Hi everyone! Today, we're going to take a look at a data structure called "Segment Tree".

A segment tree is like a linear array, so you can get an element by its index and modify it by index. However, in addition, it supports "range queries" of kind "what is the sum of all elements at indices between l and r":

  • Get element by index (return a[i])
  • Set element by index (a[i] = x)
  • Sum element at range (a[l] + a[l + 1] + ... + a[r])

Here's how not to continue:

This structure handles all these queries in $$$O(\log n)$$$ time.

Instead, you do this:

How would you handle these queries? Say you didn't need to care about performance, what's the easiest way you can imagine?

Someone says to just use an array.

That's right, we can just use an array. The first two queries will be handled in $$$O(1)$$$, but the third one is much slower, taking $$$O(n)$$$.

You draw a table with three rows and one column. The rows are named, "get", "set", and "range". The column is named "array". Complexity is written in the cells.

So this approach works fine if there are few calls of the third kind. What if that's not the case, but there were no queries of the second kind? No modifications whatsoever. You just need to sum successive elements of a fixed array. How would you solve this?

Someone says to use prefix sums. You add another column to the table, filling in rows 1 and 3.

That's right, prefix sums work in the absence of modifications. What if there were very few modifications, though? In this case, we can simply rebuild the prefix sum from scratch upon each modification in linear time.

You write $$$O(n)$$$ in row 2.

So we are clearly making tradeoffs here. Either setting is very fast and range queries are very slow or vice versa. But it turns out there's a good balance in between. The trick we'll work out in the next 15 minutes will get us to this:

Adds another column, titled "segment tree", writing $$$O(1), O(\log n), O(\log n)$$$ to the cells.

Some of you might think this is just a wall of useless text. But.

  • It brings people up to speed, quickly mentioning something they (supposedly) already know, reducing the steepness of the learning curve. They aren't just thrown into the topic, they have time to recall related notions before hearing new material. This is critical in real-time conversations.
  • It introduces the notion of tradeoffs. Space-time tradeoffs are easy to google; tradeoffs between different queries are rarely mentioned anywhere. Beginners need to realize that there isn't one option that fits all use cases, and it's fine to choose a solution based on input limits.
  • It introduces rebuilding a structure as a viable method to handle updates. This will come in handy later when sqrt decomposition is described. Acknowledging this trick early demonstrates that it's universal, and gives participants some edge.

I could go on and give examples of how to structure written posts to utilize this approach, but basically, what I'm trying to say is that teaching algorithms does not preclude teaching useful ideas and intuition. On the opposite, it simplifies the latter, because algorithms are something you can focus on and get generic ideas from, while "just solve problems" does not give newbies the right direction.

Editorial goes first

This one's admittedly clickbaity.

During the lecture, we discussed a certain topic. We then solved a contest composed mostly of problems based on this topic. So even before reading the problem, I knew what approach I was supposed to use. I then had to find the right way to apply the algorithm/data structure to the problem, and -- guess what -- that requires thinking, the skill you all say algorithms don't help to achieve.

About 20% of the problems were something we discussed and solved theoretically during the lecture. These problems trained my implementation skills. This is something beginners often lack, and, again, many of you argue algorithms don't help train that. But I think you're forgetting that implementing the algorithms themselves trains those skills, and these skills transfer to purely idea-based problems. Hell, if I got basic implementation skills from industrial programming, they can't be that unique!

These problems let me just copy-paste my code to other problems from the same contest. No "implementing the algorithm takes 70% of the time, this isn't an interesting problem" bullshit. It was the best of both worlds.

Keep to algorithmic problems, switch to idea-based problems after gaining skill

I only had success with the "go solve more problems" approach after failing at the regional stage of ROI twice. (Though the second one wasn't that much of a failure.) I don't know if the third time's a charm or what caused me to succeed the third time, but it certainly wasn't due to how much time I spent writing contests.

During this time, I studied complex topics like number theory, Knuth's optimization, Mo's algorithm, and flows. Some of them helped me directly. Others helped me cut corners: instead of inventing a cool linear solution, I'd use a segment tree on a complicated monoid.

But many of those topics helped me indirectly. My experience in utilizing data structures helped me learn decomposition. Over time, I developed a slow yet reliable way to solve a certain kind of problems. I'd implement the stupidest solution possible and then try to fit it into TL. To do this, I looked for the bottleneck, reduced it to a single computation (preferably not related to the problem at hand), and replaced it with an alternative way to compute the same value. This could be as simple as "compute the sum via a segment tree" or as hard as "use five linear passes".

In a roundabout way, solving algorithmic problems gave me tools to solve idea-based problems I struggled to solve before because the right tool was often clear in the former case, but always muddy in the second one, until I excelled in the tool.

"Go solve more problems" is for aces

I had to solve hundreds of problems independent of the algorithms because there was nothing practical to learn anymore. With segment trees, there's a high variety of problems waiting to be approached, revealing dozens of different globally applicable approaches. With the Gomory-Hu tree, not so much.

To me, the worst part about just taking part in contests was how tiring it was. It squeezed me out like nothing else did. There was little to discuss with friends. There was no time to rest. There was no feeling of progress. Understanding an algorithm you've heard of half a year ago feels great; solving one more problem on average, not so much. If you learned an algorithm but didn't manage to apply it, you still know one more algorithm than before; if you didn't solve a problem, you didn't get anything positive out of the contest.

I wasn't prepared for learning to be this hard. This demotivated me a lot. I was knowledgeable enough to realize I was good enough to push through, but I can't imagine myself starting my competitive programming career like this, with no sense of progress and no end in sight. And now we advise newcomers to start with this?

We need to do better

We have other problems with teaching. One problem I feel like I should call out is toxicity. A person I won't name (but you all will understand who I'm talking about anyway) uses a condescending tone like this:

...we all know how to read, we have our whooping 2 month of experience! Oh, my sweet summer child, my experiments show that many people with kinda cool achievements like medals on ROI don't know how to read statements. But don't worry, I'll teach you.

...in the first damn post in the Catalog. Now, I'm not saying it's their fault for it being the first post, but do we actually want to greet beginners like that in our knowledge base?


I don't have a definite learning plan that'll get you to red reliably. For all intents and purposes, "Go solve more problems" is the best we have now, even if it's wrong and there's theoretically a much better way. I don't have time nor energy to push against the grain and prepare materials the right way, alone. The best I can hope for is to start a discussion. Grab your popcorn.

  • Vote: I like it
  • +45
  • Vote: I do not like it

»
118 minutes ago, # |
Rev. 7   Vote: I like it 0 Vote: I do not like it

I agree with everything you said except two things:

  • Though there are loads of people who are unwelcoming and/or arrogant, there are a fair share of truly generous (with their time and knowledge) people. Changing this to make Competitive Programming more welcoming would mean changing the rules of the forums (no use of bad words, only pinning messages with agreeable tone, and paying people to proofread the multiple blogs in the catalog that have horrible English). That’s feasible and we shouldn’t focus on the negative. Edit: yeah I’m not really disagreeing with you now that I think about it.

  • « For all intents and purposes, "Go solve more problems" is the best we have now ». I don’t think that’s true, for newbies (which is >50% of the population here), the best we have (for people aged >18 (edit: for everyone, cf below)) is « attend a introduction to computer science and then a data structure and algorithms class in university ». And guess what, the way they teach you is exactly what you described in your post. Why? Because it is the best way to introduce concepts you’re not supposed to find on your own.

  • »
    »
    112 minutes ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Thanks for replying.

    A CS course in Uni is a great way if your university offers a good enough course. I believe that's not always the case. I don't have data, but it's not a universal solution by any means. In addition, many people start CP before 18 (which you allude to), like I did, so that option's out for them.

    But yeah, if you can get enroll in a course like that, by all means, do that, it'll boost your skill a lot.

    • »
      »
      »
      99 minutes ago, # ^ |
      Rev. 6   Vote: I like it 0 Vote: I do not like it

      Harvard has an Introduction to computer science freely available on YouTube (I think 30 hours of lectures) and MIT has a Data Structure and Algorithms course (Probably around 50 hours of lectures) freely available on YouTube. Obviously, one needs to know high school maths (induction, that kind of thing) to understand those but I'd argue they're needed anyway to do Competitive Programming. Plus, those two have English Subtitles which is good for non-native speakers (it is already hard for native speakers to understand certain non-native speakers speak or write, I can't imagine what it would feel like for non native speakers / people that only learned English in middle school).

      Although those courses are not tailored for Competitive Programming itself, trying to decode a blogpost on Medium written by someone that barely put any effort in it and that speaks approximate English when you are not in the top 5% of codeforces is in my humble opinion counter-productive.

      We really do need to stop saying (at least for those who say "I've solved my first problem, but it's super hard, how can I get better") to just spam problems and read editorials. Following a structured way of learning CS by scholars that put hours (nay weeks) into making the most logical order of learning CS is a win for those beginners.

      • »
        »
        »
        »
        93 minutes ago, # ^ |
          Vote: I like it +1 Vote: I do not like it

        That's a good argument. There's also Codeforces EDU, tailored to competitive programming in particular, but it doesn't cover many important topics. Video lectures are great resources, but for good results, you need to pair them up with thematic contests (and then multithematic contests, which unite problems utilizing different algorithms, so that you learn to guess the right approach). I don't know if anything public like that exists.

        • »
          »
          »
          »
          »
          91 minute(s) ago, # ^ |
          Rev. 3   Vote: I like it 0 Vote: I do not like it

          Codeforces EDU seems a tad too advanced when you're a newbie. If I remember correctly, they use Radix Sort without explaining how it works (which makes sense if the public you aim your videos at is experienced). Coincidentally, Radix Sort is actually taught in that MIT course I referred. But that would be the logical continuation after attending a Introduction to Data Structure & Algorithms class.

          Also, if I'm not mistaken, SecondThread did some lectures + thematic contests. I recently followed one on Treaps but there are some on easier notions.

    • »
      »
      »
      83 minutes ago, # ^ |
      Rev. 2   Vote: I like it 0 Vote: I do not like it

      as CS student at big ass state university in US

      I can confirm cf is way more involved than intro2cs or DSA it's bullshit btw.

      I really regret not have started cp before 18. i have never seen any high-rated people who started cp after 18.

      • »
        »
        »
        »
        76 minutes ago, # ^ |
        Rev. 2   Vote: I like it 0 Vote: I do not like it
      • »
        »
        »
        »
        61 minute(s) ago, # ^ |
        Rev. 4   Vote: I like it 0 Vote: I do not like it

        I did not mean Intro2cs and DSA for you. You are better than 75% users here. I meant for newbies who are currently discovering that inserting at the beginning of a dynamic array is more costly than inserting at the end of a dynamic array.

»
111 minutes ago, # |
  Vote: I like it 0 Vote: I do not like it

I made this mistake for a long time, and by doing it on my own, no one was there to help me, nor correct me. The only way I learnt was through my mistakes, by mistakes I meant by failing at competitions. By then, it's already too late. This is why I advise anyone who starts learning (people stuck in Newbie, Pupil, Specialist, or even Experts like me), please learn it right!

»
89 minutes ago, # |
Rev. 3   Vote: I like it +3 Vote: I do not like it

Great blog! and an even better decision to leave out that person's name otherwise this blog would have been downvoted just like what happened when I called him out recently and it wouldn't get many views.

A good way(not perfect) to learn in my opinion is the same way most schools follow when teaching any subject. In competitive programming, it would be something like learn a standard topic/idea, then solve problems based on that topic/idea, then repeat the same with another topic/idea. After you do this for lets say 3-5 topics, then solve problems randomly from those topics and then repeat this whole process. I think one should do this until they cover all the standard topics/ideas required to get their desired short term rating. After that, it just comes down to simply solving more problems till you get that rating and then you repeat this process I guess.

One other important thing to note is that you can infact try multiple approaches and no need to stick to one. For instance, consider the argument on when to look at solutions. Initially, you can try the approach of looking at editorial once you are stuck for 30 minutes(Errichto's advice). If that works then great, otherwise you can switch to looking at editorials as soon as you are stuck and try to figure out what insights you could have made that would have led you to arrive at the solution(Scott Wu's advice). IF that doesn't work, you can maybe forget about looking at editorials for a month and simply solve whatever problems you can and so on. You can try them all and even if one approach works you can simply try another if you are bored of the same approach or just for a change I guess. Different approaches work for different people and any approach that helps you get better while still having fun is good in my opinion.

  • »
    »
    85 minutes ago, # ^ |
      Vote: I like it +1 Vote: I do not like it

    That's what we did in the Moscow camp (and then in Sirius, so it's not just the capital). I tend to believe that's the best way to learn too.

    • »
      »
      »
      80 minutes ago, # ^ |
        Vote: I like it +1 Vote: I do not like it

      To be fair, that method of teaching (lesson then exercises on the lesson) is used in schools all over the world whether we are taught a new language, maths, computer science, chemistry, physics, .... If that wasn't ideal, countries would do better, they have huge incentives to make the best out of their education system.

»
87 minutes ago, # |
  Vote: I like it +1 Vote: I do not like it

Keep to algorithmic problems, switch to idea-based problems after gaining skill

That's exactly what AtCoder is doing, ABC contain a bunch of standard problem for beginner to learn, while ARC/AGC contain a bunch of idea-oriented problems for non-beginner to improve thinking. So I think doing AtCoder would be a good choice?

some related comment from rng_58, previous admin of AtC

  • »
    »
    81 minute(s) ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Based on that comment alone (I've never participated in AtCoder), ABCs aren't made with algorithmic problems in mind. The point of my post was that algorithmic problems help people grow, so perhaps that's what we should start with.

»
85 minutes ago, # |
  Vote: I like it +19 Vote: I do not like it

Respectfully, you are all morons.

Do you have anything except your own experience to back up your advice with?

Your a-priori reasoning is just speculation and the 1e6 nutellas who tell people to learn "ideas instead of algorithms" can also write pages of more convincing reasoning for their advice's benefits.

Also, reading the editorial before solving a problem on your own is the worst advice I ever saw.

  • »
    »
    74 minutes ago, # ^ |
    Rev. 2   Vote: I like it 0 Vote: I do not like it

    This post took me hours to write because I wanted to capture all details I thought would be important. I don't have resources to interview others about their experiences, nor boldness to ask them to reflect on their past.

    However, I think there's some things other than personal experiences in support of my theory. Russia is known to be quite great at competitive programming, and the way our largest camps teach beginners is exactly like I propose. (I only know about this in relation to school students; I think the training for ICPC is different.)

    There's also a stereotype that Chinese folk know tons of algorithms, and what we learnt from them is accidental leaks, so to speak. Segment Tree Beats is one example that comes to my mind. China has great results, so it works for them too, I guess?

    Also, reading the editorial before solving a problem on your own is the worst advice I ever saw.

    I said it's clickbaity. I don't literally advise that for all problems. All I'm saying is to do that for several easy problems while learning an algorithm, so that you get to know its theoretical applications and can spend some time improving your implementation skills without worrying about coming up with the solution right off the bat.

»
72 minutes ago, # |
  Vote: I like it +12 Vote: I do not like it

This blog is just you going "this worked for me so it is surely it is the correct way". There is a reason why high rated people have conflicting advice, people aren't "morons" for suggesting different things.

  • »
    »
    62 minutes ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I'm sorry you read it that way. This is not what I had in mind.

    I'm not saying my way is the right one. In fact, I don't even have a way, which I allude to in the closing paragraph. I'm saying that the common advice is misleading and/or useless, not that I know better.

    I haven't see high-rated folk giving significantly conflicting recommendations. It all boils down to "you need to solve more problems". I take a stance with this advice. The reason I wrote this post is that it didn't work for me, but there's more evidence than that. Few organized camps offline teach students this way. This advice is dismissive and lacks substance. You can always say "you just haven't solved enough problems" to someone who failed to succeed with this advice. I'm pretty sure survivorship bias is at play here too.

    It's not me going "everyone who dislikes the color purple is a moron". I have some, you know, arguments.

    • »
      »
      »
      47 minutes ago, # ^ |
        Vote: I like it +7 Vote: I do not like it

      I haven't see high-rated folk giving significantly conflicting recommendations

      Basic example, Um_nik has a blog where he says that you should never read editorials. Meanwhile Benq says he frequently sees editorials and sometimes he even checks them before the problem. They're both LGMs that are top 10 in the world right now, which of them is correct? One could even argue that they're both too extreme and you should do something in the middle.

      The reason I wrote this post is that it didn't work for me, but there's more evidence than that. Few organized camps offline teach students this way.

      Offline camps are great for teaching algorithms, since they're short and you have a teacher who can give you the fundamentals of that algorithm. Just because camps do it, it doesn't mean you have to do exactly as they do in camps during your whole time practicing.

      This strategy might have worked for you but there are also a lot of people who know many algorithms but can't solve problems. Your arguments aren't some masterpiece that back statements like "This is not how you teach competitive programming" and "And now we advise newcomers to start with this?"

      People learn differently, there isn't a perfect method for getting good. The only thing that is common between all training methods is that you solve a lot of problems. That's why its the prevalent advice.

      • »
        »
        »
        »
        21 minute(s) ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        It is easy to refute your example: everything Um_nik says is bullshit and also he is rude so his opinion is automatically wrong.

»
71 minute(s) ago, # |
Rev. 2   Vote: I like it +3 Vote: I do not like it

The way i see it, “go solve more problems” is equivalent to “git gud”. The thing is, I would say that most of the cpers (if we exclude people from countries like Russia) are self-taught. And there are tons of resources online that have good roadmaps for beginners (like usaco.guide or cses.fi), so when someone asks for the 1000th times “how do i get good” or “how do i reach X rating”, “solve more” is just a polite way of saying “git gud”.

The “Start with algorithms” part is also controversial. I think that general consensus on “Ideas >>> Algorithms” comes from the many examples of people going “I tried to solve X using Y, but it didn’t work” or “can X be solved with Y?” It was discussed more thoroughly in this blog. The fact is, many people that are asking these questions half-learned some algorithms and then try to apply them to any problem they see, which also results in frustration when they meet conventionally easier problems that don’t use any ds or algo. I myself is an example of this situation, because I was solving 2400+ data structures problems when I was only a specialist. I don’t regret it, since it was a lot of fun to do, but encountering situations where I couldn’t solve a binary search problem in the contest while I was thinking that I’m strong because I could implement Li-Chao tree was indeed frustrating. I agree that algorithms teach you implementation skills, but you can acquire them by solving regular implementation (like the first section of cses). The only downside I see for the approach “Ideas >>> Algorithms” is the fact that we don’t have a list for these ideas, except blogs like this one.

  • »
    »
    67 minutes ago, # ^ |
      Vote: I like it +2 Vote: I do not like it

    Also, reading the editorial before attempting to solve the problem is a weird advice. If you try to solve the problem on your own first, you'll likely remember it better than if you just read the editorial.

»
63 minutes ago, # |
  Vote: I like it 0 Vote: I do not like it

I think the problem lies mostly with the dogmatic answers we usually see, instead of a certain approach being "right". Personally, I had the exact opposite experience you had: I tackled problems before even knowing what time complexity was, and it was fun. A lot of fun.

Again, this isn't about which one is the "better" way. I simply think that we should let beginners experiment a bit more. It doesn't really matter if a newcomer is learning new tricks or solving problems, as long as they consistently do something, they'll reach the stage where they can solve problems on their own.

»
55 minutes ago, # |
  Vote: I like it +11 Vote: I do not like it

I'm not sure to whom you're writing this blog. No university teacher only tells students to solve problems. The authors of "solve problems (and learn a new topic when you encounter it)" comments are not teachers, i.e. such a comment isn't about teaching, it's just a piece of advice. And it is a good advice. If you prefer the more structured way (e.g. read an algo book) then sure, it's your preference.

Your example with a segment tree actually shows that it's good to try to solve a problem first instead of immediately learning the algorithm / data structure.

»
21 minute(s) ago, # |
  Vote: I like it +1 Vote: I do not like it

Activities for poor competitive programmers

»
15 minutes ago, # |
  Vote: I like it 0 Vote: I do not like it

I'm sorry if my thoughts on this blog will be a bit unstructured.

I think the main difference between examples you started with is lack of examples, simply explaining an algorithm/idea without showing how to apply it isn't very efficient.

I don't think there is a fundamental difference between an algorithm and an idea. Idea is a more specific algorithm. So learning algorithms is generally easier and more useful, but the general learning rule sounds like "learn topics in order of increasing difficulty", so it will probably favor learning algorithms sooner but not as rigidly as you seem to suggest.

Most people like us probably started learning with sections and camps (with lectures and theme contests), writing stuff like CF only for fun, not learning, and started solving problems without given topics only in preparation for olympiads. Codeforces isn't very well suited for theme contests, but there are publicly available resources for that like cses.fi, I think it's important that newcomers don't limit themselves to staying on Codeforces.

On the last topic, based on what I've seen the person you mentioned say about problems and people, I'm convinced that they have no idea how a person even of my level thinks, let alone someone from the target audience of their educational resources. People think they can get good advice from them just because of high rating which means very little in terms of teaching skill. For now I don't know of a way for newbies to distinguish good educational resource from a bad one, blog's rating doesn't work for this

I think that's a pretty good blog, I agree with a lot of your points and I haven't really thought about teaching aside from offline stuff (most of it already adheres to your advice) before