Why this matters when you build with AI
When you build with AI tools, the scarce thing is your attention and your hours, and the tools will happily use as many of them as you let them. A model will keep proposing a fresh approach for as long as the conversation runs, and it will not tell you that the last hour has produced nothing. A contest has the same trap in a sharper form. The clock runs whether you are making progress or not, and the only person who can stop you is the rule you set before you started. This lesson gives you that rule, and a way to check afterwards whether you followed it.
The idea: time is the cost of a problem
In a contest, the cost of a problem is mostly minutes. Each problem has a value in points, a chance of being solved in the time you give it, and a time you are willing to spend. The question at every moment is simple: is the next minute on this problem worth more than the next minute on any other problem?
Two words will be used throughout.
- A budget is the number of minutes you plan to spend on a problem before you reconsider.
- A stop rule is an if-then rule that says when to stop working on the current problem. For example: "if I have no new idea for 15 minutes, I switch."
A budget tells you when to look at a problem again. A stop rule tells you what to do when you look.
Setting a budget from difficulty
Start from the contest length and reserve some time for the opening scan from lesson 01, and for the final checks.
The formula is:
pool = contest minutes - reserve minutes
budget for a problem = pool * weight / sum of all weightsThe weight is a number you choose for each difficulty tag, for example 1 for easy, 2 for medium and 3 for hard. The weights do not have to match the points; they match how long you expect the problem to take.
A worked example. Suppose the contest is 240 minutes, the reserve is 20 minutes, and there are six problems: two easy, two medium and two hard. The weights are 1, 2 and 3.
pool = 240 - 20 = 220
sum of weights = 2*1 + 2*2 + 2*3 = 12
minutes per weight = 220 / 12 = 18.33
easy budget = 1 * 18.33 = about 18 minutes
medium budget = 2 * 18.33 = about 37 minutes
hard budget = 3 * 18.33 = about 55 minutesThe budgets add up to about 220 minutes, which leaves the reserve for scanning and checks. If your tags are wrong, the budgets are wrong too, which is why lesson 01 asks you to revisit the tag when a problem proves harder or easier than expected.
Write the budget next to each problem in your scan table. You do not have to keep to it exactly. The point is to have a number that makes the decision to stop a question you answer, not one you argue with yourself about in the middle of a bad hour.
Stop rules
A stop rule needs three parts: a trigger you can see, an action, and a cost you accept. Here are the three rules that do most of the work.
Rule 1: no new idea for N minutes
Choose N before the contest. A good start is 15 minutes for a medium problem and 25 for a hard one. The trigger is the absence of a new idea. Writing "I am still checking my code" is not a new idea.
The action is to write one line of what you tried, then switch to the next problem on your list. You can come back later, with the line as your starting point.
Rule 2: wrong submissions have a price
Wrong answers cost time, and in most ICPC-style contests they also cost penalty. In the standard ICPC rules, a team's time for a solved problem is the minute of its first accepted submission, plus 20 minutes for every wrong submission before that accepted one. Unsolved problems add nothing to the penalty. The ICPC East Central North America rules page (icpc-ecna.ysu.edu/rules.html) and the UCSB ICPC FAQ (sites.cs.ucsb.edu/~daniello/icpc2025/faq.html) both describe this 20-minute rule with a worked example. The ECNA page also says that a compile error does not add the 20 minutes. Other platforms use other rules, so read the rules page of the contest you enter.
Here is what that means in practice. A problem solved at minute 120 after two wrong answers gives 120 + 2 * 20 = 160 penalty minutes. The same problem solved at minute 120 with no wrong answers gives 120. The two wrong answers cost 40 minutes of ranking, not 40 minutes of the clock. In a contest decided by penalty, that difference matters.
The rule for submitting is then:
- Before you submit, check the answer on the sample input and on one small case you work out by hand.
- After one wrong answer, do not resubmit the same code. Find the bug first.
- Do not submit a guess. A guess that is wrong costs 20 minutes if you later solve the problem.
Rule 3: the budget is spent
When the minutes you planned for a problem are gone, stop by default. Stop means you note where you are, and you move on. You may return later, but only if your other problems are worse, judged by the same rule.
Sunk-cost bias
Sunk cost is a term from economics and psychology. A sunk cost is a cost you have already paid and cannot get back. Sunk-cost bias is the habit of letting a past cost decide a future choice. It is the most common reason competitors stay on a problem after they should have left.
A concrete example. You have spent 50 minutes on problem C. Your last idea failed. You now have two options:
- Option 1: problem C. The next idea needs about 30 minutes, and you think it has a 30 percent chance of working.
- Option 2: problem D. You already know the method and it needs about 20 minutes, with an 80 percent chance.
Both problems are worth 10 points. The 50 minutes are gone either way, so they do not count in the decision. Compare the expected points per future minute:
option 1: 10 * 0.30 / 30 = 0.10 points per minute
option 2: 10 * 0.80 / 20 = 0.40 points per minuteOption 2 is four times better per minute. A competitor who thinks "I have put 50 minutes into C, I cannot waste that" picks option 1 and loses the chance to score on D.
The test for sunk-cost bias is one question: "If I were starting this problem fresh now, with the same time left, would I choose it?" If the answer is no, leave it, whatever you have already spent.
A stop-rule table
Write this table on paper before the contest. Fill in the numbers that suit you, then keep the table in front of you during the contest.
| Situation | Rule | Action |
|---|---|---|
| No new idea on the current problem for N minutes | N = 15 for medium, 25 for hard | Write one line about what you tried, switch to the next problem on your list |
| A wrong answer | Do not resubmit before a small hand test | Test on the sample and one hand case, then fix |
| Two wrong answers after an idea you believed in | Stop the idea | Switch and note the failing case |
| Budget for the problem is spent | Stop by default | Note the state and move on |
| Choosing between a sunk problem and a fresh one | Compare points per future minute | Pick the higher rate, ignore time already spent |
| Ten minutes left | Submit only what you have tested | Stop starting new ideas |
The table is your own. Change the numbers after one or two practice contests, and keep the rules that you actually followed.
Standard technique: a scoreboard calculator
To check the penalty rule, write the calculation as a program. The program reads a submission log and prints, for each problem, whether it was solved, the minute of the first accepted submission, the number of wrong answers before it, and the penalty. The log is the list of your submissions in time order.
The logic is short. Ignore a submission to a problem already accepted. Count a wrong answer for each submission that is not AC (accepted) and not CE (compile error). On the first AC, record the time and mark the problem solved. The penalty for a solved problem is the time plus 20 times the wrong count.
Compile with g++ -std=c++17 -O2 -Wall -o scoreboard scoreboard.cpp.
// scoreboard.cpp: ICPC-style scoreboard from a submission log.
// Input: p m p = number of problems (numbered 0..p-1), m = number of submissions
// then m lines: minute problem verdict
// minute = minutes since contest start (integer, sorted ascending in the log)
// verdict = AC (accepted), CE (compile error, no penalty), anything else = wrong answer
// Rule: a solved problem costs (minute of first AC) + 20 * (wrong submissions before that AC).
// Submissions after the first AC do not count. Unsolved problems cost nothing.
// Output: one line per problem: index solved minute_of_ac wrong penalty
// (wrong = wrong submissions before the AC, or all wrong submissions if unsolved)
// then a final line: total_solved total_penalty
#include <bits/stdc++.h>
using namespace std;
int main() {
int p, m;
if (!(cin >> p >> m)) return 0;
vector<bool> solved(p, false);
vector<long long> acTime(p, 0), wrong(p, 0);
for (int k = 0; k < m; k++) {
long long minute;
int prob;
string verdict;
cin >> minute >> prob >> verdict;
if (solved[prob]) continue; // already accepted: later submissions do not count
if (verdict == "AC") {
solved[prob] = true;
acTime[prob] = minute;
} else if (verdict != "CE") {
wrong[prob]++; // compile errors are not penalised
}
}
int totalSolved = 0;
long long totalPenalty = 0;
for (int i = 0; i < p; i++) {
long long penalty = 0;
if (solved[i]) {
penalty = acTime[i] + 20 * wrong[i];
totalSolved++;
totalPenalty += penalty;
}
cout << i << " " << (solved[i] ? 1 : 0) << " " << acTime[i] << " " << wrong[i] << " " << penalty << "\n";
}
cout << totalSolved << " " << totalPenalty << "\n";
return 0;
}Worked example on a small input
Here is a log for three problems. Problem 0 gets a wrong answer at minute 15 and is accepted at minute 70. Problem 1 gets three wrong answers and is never solved. Problem 2 gets a compile error at minute 50, then is accepted at minute 60.
3 7
15 0 WA
70 0 AC
20 1 WA
30 1 WA
40 1 WA
50 2 CE
60 2 ACThe output is:
0 1 70 1 90
1 0 0 3 0
2 1 60 0 60
2 150Check it by hand. Problem 0: accepted at 70 with one wrong answer, so 70 + 20 = 90. Problem 1: never accepted, so no penalty, but its three wrong answers are shown. Problem 2: the compile error does not count, and the accepted time is 60, so 60. Two problems solved with a total penalty of 150. The program agrees with the hand count.
The check against a second version
A bug shows up clearly on a second log. Take this one: four problems, nine submissions.
4 9
10 0 WA
25 0 WA
40 1 CE
42 1 AC
50 0 AC
55 2 WA
60 2 TLE
61 1 WA
200 2 ACThe correct program prints:
0 1 50 2 90
1 1 42 0 42
2 1 200 2 240
3 0 0 0 0
3 372Now take out the line that skips submissions after the first accepted one, and run it again. The result changes as follows:
0 1 50 2 90
1 1 42 1 62
2 1 200 2 240
3 0 0 0 0
3 392Problem 1 now shows a penalty of 62 instead of 42. The bug counted the wrong answer at minute 61, which came after the accepted answer at minute 42. The total is 392 instead of 372. This is the symptom to watch for: a penalty that is higher than the accepted minute plus twenty times the wrong answers before it.
I compiled the correct version with g++ -std=c++17 -O2 -Wall and tested it on 500 random logs with 1 to 5 problems, up to 25 submissions, and verdicts chosen from AC, WA, CE and TLE. A separate Python version that follows the same rule printed identical output on all 500 logs. Both versions follow the rule as written here. If your contest uses a different rule, change both the program and the test.
Complexity
Time is linear in the number of submissions, O(m + p). Memory is O(p). A log of a few hundred lines runs instantly.
Where did the minutes go? Auditing a timeline
A scoreboard tells you the result. It does not tell you where the time went. For that you need a timeline of what you were doing, and a stop rule to check it against.
The timeline below is a simulated contest. Each line is minute event problem, with four events:
open: you started working on a problem.idea: you got a new idea for the problem.wrong: you submitted a wrong answer.ac: the problem was accepted, so it is finished.
The audit gives each stretch of time to a problem and then checks it against the stop rule. The stop rule is: N minutes after the last open or idea on a problem, time spent on that problem is stale. Stale time is time spent without a new idea, past the N-minute grace period.
The program takes the log from a text string, so it runs with no input. Run it with python3, the standard Python 3 interpreter.
Its output is:
stop rule N=15 min, contest end=180
problem minutes stale wrong
- 6 0 0
A 74 36 2
B 48 15 2
C 52 25 1
total minutes: 180, stale minutes: 76Read the table this way. Problem A had 74 minutes, and 36 of them were stale. Those 36 minutes are the stretch from minute 20 to 34, where the wrong answer at 20 led nowhere for 11 minutes after the grace period, and the stretch from 122 to 150, where no new idea came for 25 minutes. Problem B had 48 minutes with 15 stale, from minute 165 to 180, the end of the contest without a new idea. Problem C had 52 minutes with 25 stale: its long stretch from minute 60 to 95 was about 20 minutes beyond the grace period, and the wrong answer at 95 added 5 more before the next idea at 100.
The - row is 6 minutes after the accepted problem C was finished, before a new problem was opened. That time is not wasted on a problem; it is the gap between problems.
Check the program's arithmetic on one line. Problem C from minute 60 to 95: the last idea was at 60, so the grace period ends at 75. The interval runs to 95, so 95 - 75 = 20 stale minutes. The program's total of 25 for C adds the 5 minutes from 95 to 100, which is the wrong answer at 95 with no new idea before 100.
I ran this script without changes and the output above is what it printed. The stale count depends on N, so change N and rerun to see how the picture changes.
Common mistakes
Counting wrong answers after the first accepted one. The symptom is a penalty larger than the accepted minute plus 20 times the wrong count before it. The sample in the section above shows 62 for a problem that should show 42.
Counting compile errors. Many contest rules do not penalise them. Check the rules, and keep compile errors out of the wrong count if your rules say so.
Treating the budget as a promise. A budget is a point to reconsider, not a law. Ignore it only when you can name the new idea and its expected payoff.
Using the sunk cost as the reason. The symptom is a sentence like "I have already spent an hour on this." That sentence describes the past. The next decision needs the minutes you have left.
Setting N too small. A 3-minute rule means you switch every time you pause to think, and you never finish a hard problem. Set N from the difficulty tag, and use the table to revise it after a contest.
Trusting an AI model to tell you when to stop. A model answers each question at similar length, whatever the problem is worth, and it rarely says that the next idea is not worth testing. Its brute force checks can carry the same bugs as its fast code. Keep the stop rule in your own table, and check a model's claimed fix against the sample input and a small hand case before you spend time on it.
Checklist
- Write the contest length, the reserve, and a budget for each problem before the contest starts.
- Write the stop-rule table with N for each difficulty.
- Before a submission, run the sample and one hand case.
- After one wrong answer, test before resubmitting.
- When a budget is spent, write one line of state and move on by default.
- When choosing between problems, compare points per future minute, not time already spent.
- After each practice contest, log the timeline and run the audit. Change one rule and try it again next time.
Exercise on your own machine
- Save the scoreboard program from this lesson as
scoreboard.cpp, compile it, and run it on the practice log above. Check the output by hand. - Save the timeline script as
timeline_audit.pyand run it withpython3 -I timeline_audit.py. Confirm the output matches the table above. - Write a timeline for your last practice contest or virtual round: at least 10 events, using
open,idea,wrongandac. Use real minutes from your notes, and say in your notes which times are estimates. - Put your log in the
LOGstring and run the audit. Write down the problem with the most stale minutes and the single event where the most stale time started. - Change N from 15 to 25 and run again. Write one sentence on whether your conclusion changes.
Your numbers will differ from the examples, which is the point. The program prints only integers and the same log gives the same output on any machine.
Practice problems
1. Budget arithmetic. A contest lasts 300 minutes. The reserve is 30 minutes. There are eight problems: three easy (weight 1), three medium (weight 2) and two hard (weight 3). What is the budget in minutes for each difficulty, to the nearest minute?
Hint: add the weights first, then divide the pool by that sum.
Show the answer
The pool is 270 minutes. The sum of weights is 31 + 32 + 2*3 = 15. Each weight is worth 270 / 15 = 18 minutes. Easy gets 18, medium gets 36, and hard gets 54 minutes.
2. Penalty by hand. The log below is for three problems. Work out, without running the program, the accepted minute, the wrong count and the penalty for each problem, and the totals. Then run scoreboard to check.
3 6
10 0 WA
25 0 AC
30 1 WA
40 1 WA
45 2 CE
50 2 WAShow the answer
Problem 0 is accepted at 25 after one wrong answer: 25 + 20 = 45. Problem 1 is never accepted, so its penalty is 0 and its wrong count is 2. Problem 2 has a compile error and then a wrong answer, never accepted, so its penalty is 0 and its wrong count is 1. Totals: 1 solved, penalty 45. The program prints:
0 1 25 1 45
1 0 0 2 0
2 0 0 1 0
1 453. Find the lost minutes. Change the LOG string in the timeline script to this log, with N = 15 and END = 180. Which problem has the most stale minutes, and which stretch causes most of them?
0 open A
12 idea A
30 wrong A
45 wrong A
60 idea A
64 ac A
66 open B
70 wrong B
100 wrong B
130 idea B
140 wrong B
170 wrong BShow the answer
The output is:
stop rule N=15 min, contest end=180
problem minutes stale wrong
- 2 0 0
A 64 33 2
B 114 84 4
total minutes: 180, stale minutes: 117Problem B has the most stale minutes, 84 of its 114. The largest stretches are from minute 100 to 130, which is 30 minutes with no new idea since the open at minute 66, and from minute 145 to 170, which is 25 minutes after the idea at 130 whose 15-minute grace period ended at 145. Problem A's stale time comes from its two wrong answers at 30 and 45, which came without a new idea after the idea at 12.
4. Sunk cost in a decision. You have spent 60 minutes on problem X. A new idea would take 25 minutes and has a 40 percent chance. Problem Y is worth the same points and you know its method, which needs 20 minutes at 70 percent. Which do you pick, and what would you say to yourself if you were tempted to stay on X?
Show the answer
Pick Y. Compare future points per minute: X gives 0.4 * points / 25 = 0.016 times the points per minute, and Y gives 0.7 * points / 20 = 0.035 times the points per minute, which is more than twice as much. The 60 minutes on X are gone either way. The sentence to say to yourself is: "The 60 minutes are spent, and the next 25 minutes on X are worth less than 20 minutes on Y."
5. Write your own stop-rule table. Write a stop-rule table for your next contest, with at least four rows. Each row needs a trigger you can see, an action, and a number.
Show the answer
There is no single correct table. A good answer has a numeric trigger, for example "15 minutes with no new idea", not "when I feel stuck". Each action is something you can do in under a minute, such as writing one line of notes and switching. Check the table after one practice round: any row you did not follow is either wrong or too hard to follow, and you should change it.
Summary
Set a budget from difficulty, write stop rules with numbers, and treat time already spent as spent. Then check your rules against a logged timeline, because the lost minutes are easy to miss while you are working.