Skip to content
Embercode
✕
Contest strategyLesson 8 of 10

35 min read

Virtual contests and upsolving

Why this matters when you build with AI

An AI tool can explain the idea of any contest problem within seconds. That speed is the trap. If you read the explanation before you have tried, the problem feels easy afterwards, and you learn very little from it. A practice round tells you what you can do alone in the time you have. Upsolving, which means solving the missed problems after the round, tells you what you could not do yet, and why.

AI tools also make mistakes in this work. An AI-written editorial summary can name the right technique and then describe a step that is false. It can also write a post-mortem that invents a cause, such as "I ran out of time on the proof," when your log shows that you spent 40 minutes on a wrong first idea. The habit to build is simple: every claim about what happened, and every claim about what the solution does, gets checked against a log or a test.

The idea: an honest round and an honest review

A virtual contest is a timed practice round on a past problem set, run as if it were live. "Virtual" means you are not in the real contest, so nobody is watching. That makes honesty your job. The round only helps you if its timing and rules are real. Sites differ in how they record virtual results, so read the current rules page of the site you use before you rely on any rating or standing.

The rules you set for yourself

Before you start, write down four rules, and keep them for the whole round.

  1. Same time. Use the time limit of the real contest, or a fixed block such as 90 or 120 minutes. Start the timer when you start reading, and stop it when the time is up, even if you are in the middle of a thought.
  2. No hints. Do not open the editorial (the official solution write-up), the tags (short labels such as "greedy" or "graph" that some sites show on each problem), the solve counts, or any discussion while the round runs. A tag tells you the technique before you have found it, so your attempt is no longer a test of finding it yourself.
  3. No people. Do not ask a friend or a forum for help during the round.
  4. Only the tools the set allows. If the set allows your own notes and templates, use them. If it bans AI tools, or if you decided beforehand not to use them, do not use them during the round. Write down any help you took, so the log is honest.

These rules are not about morality here. They are about the data you collect. A round with peeking produces a score that looks better than your real skill, and your next plan is built on that wrong number.

What a virtual round is for

A round tells you three things. It tells you which problems you can solve in the time, how long each one takes, and where the time went. Those three facts feed the plans in the lesson on practice plans. The score on its own matters less than the timeline.

What upsolving is for

Upsolving is solving the problems you did not finish, after the round is over and with the editorial available. The order matters.

  1. Spend a fixed block, such as 30 minutes, trying the missed problem again with no editorial. Write your best idea, even if it is wrong, and test it on small inputs.
  2. Read the editorial for the idea only. Stop reading as soon as you know the technique.
  3. Close the editorial and write the solution yourself, from the idea.
  4. Test your solution against a brute force on random small inputs, as the lesson on stress testing describes.
  5. Write one line about what you were missing, so you can find that gap in later rounds.

Upsolving is not copying. If you read the full code before you have tried the idea yourself, you have studied a solution, not solved a problem. The idea is to finish with a solution you wrote and tested.

The post-mortem

A post-mortem is a short written review of a round. It has four parts: the score, the timeline, the causes of lost time, and one rule to change for the next round. It is written soon after the round, while the log is fresh. A post-mortem should be short enough to read in two minutes.

Standard technique: the round loop

A round has five steps, and each one leaves a record.

  1. Set up. Pick the set, write the length of the round, and write the start time in your log file.
  2. Run. Every time you submit, add one line to the log: the clock time since start, the problem letter, and the verdict. Use OK for an accepted submission and WA for a wrong answer. Write the line when you see the verdict, not later.
  3. Stop. When the time is up, stop the timer and stop working. Note the stop time.
  4. Score. Run a helper on the log (below) to get the solve times and the penalty. Write the numbers down.
  5. Review. Upsolve the missed problems, then write the post-mortem.

A log helper

The log is a plain text file. Each line holds the time since the start (as minutes and seconds), the problem letter, and the verdict. Lines that start with # are comments. The helper below reads the log and prints one row per problem.

It uses ICPC-style scoring, a common rule. A solved problem costs the minute of its first accepted submission, plus 20 minutes for each wrong attempt before it. Other contests use other rules, so change the constant PENALTY if your set uses a different one, and check the rules of the set.

import sys
 
# Reads a hand-kept contest log, one event per line:  MM:SS  PROBLEM  VERDICT
# VERDICT is OK for an accepted submission, anything else is a wrong attempt.
# Scoring used here is ICPC style: a solve costs its minute plus 20 minutes per
# earlier wrong attempt on that problem. Change PENALTY for other rules.
PENALTY = 20
 
attempts = {}   # problem -> wrong attempts so far
solved = {}     # problem -> minute of the accepted submission
lines = [l.strip() for l in open(sys.argv[1]) if l.strip() and not l.startswith("#")]
for line in lines:
    clock, problem, verdict = line.split()
    mm, ss = clock.split(":")
    minute = int(mm) + int(ss) / 60
    if problem in solved:
        continue  # later submissions to a solved problem do not count
    if verdict == "OK":
        solved[problem] = minute
    else:
        attempts[problem] = attempts.get(problem, 0) + 1
 
total = 0.0
print(f"{'problem':8} {'wrong':>5} {'solved at':>10} {'cost':>8}")
for p in sorted(set(attempts) | set(solved)):
    wrong = attempts.get(p, 0)
    if p in solved:
        cost = solved[p] + PENALTY * wrong
        total += cost
        print(f"{p:8} {wrong:>5} {solved[p]:>10.1f} {cost:>8.1f}")
    else:
        print(f"{p:8} {wrong:>5} {'-':>10} {'-':>8}")
print(f"solved {len(solved)}, penalty total {total:.1f}")

The helper only reads the log. It does not check the code you wrote, so a solve in the log means only that the judge said OK. Save it as contest_log.py and run it with python3 contest_log.py yourlog.txt. It needs Python 3.6 or later for the f-strings.

Worked example: a 120-minute round

This log was made up for the lesson. It is not a real contest, so the numbers only show how the helper and the post-mortem work. The round had four problems, A to D, and a 120-minute limit.

# virtual round, 120 minutes, timeline kept by hand
04:10 A WA
11:05 A OK
20:00 B WA
33:30 B WA
41:20 B OK
62:00 C WA
75:10 C WA
110:40 C WA
118:05 D WA

Here is the helper's output on this log. We ran it in the scratch folder with Python 3 on Linux.

problem  wrong  solved at     cost
A            1       11.1     31.1
B            2       41.3     81.3
C            3          -        -
D            1          -        -
solved 2, penalty total 112.4

Check one row by hand. Problem A has one wrong attempt at 04:10 and an accepted one at 11:05. The solve time is 11 minutes and 5 seconds, which is 11.08 minutes and shows as 11.1. The cost is 11.1 + 20 × 1 = 31.1. The helper matches.

The helper ignores the submissions after a solve. Here is a second log, also made up, that checks that rule.

30:00 X OK
40:00 X WA
60:00 Y WA
70:00 Y WA

The output was:

problem  wrong  solved at     cost
X            0       30.0     30.0
Y            2          -        -
solved 1, penalty total 30.0

The wrong attempt on X at 40:00 came after the solve, so it does not count. Y has two wrong attempts and no solve.

The post-mortem

Fill in a template like this one, using only facts from the log and your notes.

Round: [name of the set, number of problems, length in minutes]
Score: [solved count, penalty total from the helper]
Timeline: [two or three facts from the log, with clock times]
Time lost: [the two biggest causes, with the minutes they cost]
Rule for next round: [one rule, one sentence, that would have saved the most time]
Missed problems to upsolve: [letters]

For the round above, a filled template could read:

Round: practice set, 4 problems, 120 minutes
Score: 2 solved, penalty total 112.4
Timeline: A solved at 11:05 after one wrong try. B solved at 41:20 after two wrong tries.
          C got three wrong tries between 62:00 and 110:40, and was not solved.
Time lost: C had three wrong tries and no accepted answer. B's two wrong tries
           added 40 penalty minutes.
Rule for next round: after two wrong tries on one problem, stop and check the sample and a
                     small case by hand before the next submission.
Missed problems to upsolve: C, D

Each claim in that post-mortem comes from the log. Counting the minutes C took is harder than it looks, because the log holds only the attempts. The helper does not measure time spent thinking, so do not write "C cost 50 minutes" unless you have a timestamp for when you started C. If you write a claim you cannot point to in the log, remove it.

Upsolving C

Suppose C is a problem from the lesson on partial scores: the "Exact train" problem. The round gave three wrong tries, so the plan is as follows. Spend 30 minutes trying the problem again with no editorial. Write the subtask 1 solution first, because it is simple and checkable. Then test a faster idea against it on small inputs. Only then read the editorial, and only for the idea.

Hands-on exercise

Run a real round on your own machine. Pick a set of three or four problems from a past contest that you have not seen, or a timed problem set from this course. Use a 90-minute limit. Keep the four rules from the start of this lesson, and write a log as you go. When the time is up, run the helper and fill in the post-mortem.

A good answer has a log with a line for every submission, a helper output that matches your hand check of one row, and a post-mortem where every claim points to a log line. A weak answer has a post-mortem with a reason that is not in the log, such as "I was tired," with no evidence.

Here is a prompt for reviewing a post-mortem. Use it on your own draft.

Here is my post-mortem for a 90-minute virtual round, and the log it came from.
For each claim in the post-mortem, say whether the log supports it. If a claim is
not supported, mark it "not in log" and do not guess a replacement. Then say whether
the rule for the next round would have changed a line in the log, and which line.
Log:
[paste the log]
Post-mortem:
[paste the post-mortem]

A good answer marks each unsupported claim, and does not invent new facts. Check its claims against the log yourself, because an AI tool can agree with a claim it has not checked.

Common mistakes

Peeking at tags. A tag such as "graph" tells you the family of the idea before you start. The symptom is a solution that appears in two minutes after a glance at the tags, and a log that shows no real search for the idea. The round then tells you nothing about your skill.

Logging a solve from the upsolve. A problem solved later with the editorial is not a solve in the round. Keep the round's log separate from your upsolving notes, so the score stays honest.

Starting the timer late or stopping it late. If the timer starts after you have read the problems, the round is too short in your log and the penalty times are wrong. If you keep working after the stop time, the score is too high. The symptom is a helper output with times past the round length.

Writing the post-mortem a week later. Memory changes. Reasons drift toward the one that sounds best. Write the post-mortem the same day, from the log.

Trusting an AI editorial summary. An AI tool can state the right idea with a wrong detail, such as a claim that a greedy choice always works. Test any claim on small random inputs against a brute force before you keep it in your notes. If the claim fails on a small input, the summary was wrong, and you should check the editorial itself.

Treating the helper as a judge. The helper counts what you logged. It does not check the code. A solve counts only when the judge gives OK.

Checklist

  • Write the four rules (same time, no hints, no people, allowed tools) before you start the round.
  • Start the timer when you start reading, and log every submission at once.
  • Stop the timer at the end, even mid-thought, and record the stop time.
  • Run the helper and check one row by hand.
  • Upsolve each missed problem: try for a fixed block, read the idea only, write and test your own code.
  • Write the post-mortem the same day, and point each claim to a log line.
  • Change one rule for the next round, based on the biggest loss in the log.

Summary

A virtual round is useful only when its timing and rules are honest. The log is the record: it gives the solve times and the penalty, and it shows where the minutes went. Upsolving finishes what you missed, in an order that keeps the thinking yours. The post-mortem turns the log into one rule for the next round, and every claim in it should be traceable to a line in the log.

Practice

Each practice problem is original. Work on paper or in a file, then check the answer section.

  1. Score a log. Here is a log for a 60-minute round with problems P, Q and R. Compute the solve time, wrong attempts and cost for each problem with the ICPC rule, using the helper or by hand. Say which problems are solved.

    05:10 P WA
    09:20 P OK
    18:00 Q WA
    25:30 R WA
    31:00 Q WA
    44:40 Q OK
    52:00 R WA
    58:10 R WA
  2. Find the bad claim. A post-mortem says: "We lost 30 minutes on problem S because the time limit was too tight." The log has one line for S: 50:00 S WA, and the round ran for 120 minutes. What is wrong with this claim? Write a claim the log does support.

  3. Upsolve plan. You missed a problem with an O(N²) idea that is too slow for N = 200000. Write a plan for upsolving it in 60 minutes, with the time for each step, and say what you would test first.

  4. Set a rule. A round log shows that two problems were each attempted three times before a solve, and each was a simple off-by-one error. Write one rule for the next round that would have caught these errors earlier, and say what it costs in time.

  5. Honest rule. A friend says it is fine to read the tags during a virtual round, because "it is only practice." Write a short reply that explains what the friend would lose, using the idea that the round measures your own skill.

Show the answer

  1. P: solved at 09:20 (9.3 minutes), 1 wrong, cost 29.3. Q: solved at 44:40 (44.7 minutes), 2 wrong, cost 84.7. R: not solved, 3 wrong. Solved count is 2, and the penalty total is 114.0. The helper printed exactly these values.

  2. The claim says the time limit caused the loss. The log has only one line for S, a single wrong attempt at 50:00, and nothing after it. The log cannot show a time-limit cause, and it shows only one wrong attempt. A supported claim is: "S got one wrong attempt at 50:00 and was not solved again. The round had 70 minutes left after that attempt."

  3. A plan: 5 minutes to restate the problem and its limits. 10 minutes to write the O(N²) idea and count its steps. 15 minutes to read the editorial for the idea only, then close it. 20 minutes to write the faster solution. 10 minutes to test against a brute force on random small inputs. The first test is the sample, then a small random comparison.

  4. Rule: before a second submission on any problem, check the sample and one small case by hand, and write the expected output in the log. This costs about two minutes per check and catches off-by-one errors on the first wrong attempt. A correct sample check does not prove the code is right, so it is a filter, not a guarantee.

  5. A reply: "If you read the tags, the round tells you whether you know the technique once it has a name. It does not tell you whether you can find it. Practice that skips the search gives a score you cannot trust, and the next round will show it." Use your own words, but keep the point that a score measures what you did alone.

Practice this topic: coding problems for Contest strategy →
← Partial scores and subtasks