USACO 2015 December · Bronze · all three problems
Problem 1 — Fence Painting
Statement
Farmer John paints the fence from x=a to x=b. Bessie paints from x=c to x=d. The two intervals may overlap. Output the total length of fence that ends up with paint on it (i.e., the length of the union of [a,b] and [c,d]).
Constraints
- 0 ≤ a < b ≤ 100, 0 ≤ c < d ≤ 100.
- All inputs are integers.
- Time limit: 2s. Memory limit: 256 MB.
Key idea
Union length = (b − a) + (d − c) − overlap, where overlap = max(0, min(b, d) − max(a, c)). With the coordinate range capped at 100 you can also just mark a boolean array of 100 unit-segments and count the true entries, which is more obviously correct under contest pressure.
Complexity target
O(1) arithmetic, or O(100) brute mark — both trivial.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int a, b, c, d;
cin >> a >> b >> c >> d;
// Mark each unit segment [i, i+1) for i in [0, 100).
bool painted[100] = {false};
for (int i = a; i < b; ++i) painted[i] = true;
for (int i = c; i < d; ++i) painted[i] = true;
int total = 0;
for (int i = 0; i < 100; ++i) if (painted[i]) ++total;
cout << total << "\n";
}
Pitfalls
- Disjoint intervals. If [a,b] and [c,d] don't touch you must still sum both lengths — the formula handles that via max(0, ...).
- Off-by-one with unit segments. [a,b] covers b−a unit segments (indices a..b−1).
- Don't double-count the overlap. The boolean-array approach makes this impossible by construction.
- Coordinates are tiny. No overflow, no need for long long.
Problem 2 — Speeding Ticket
Statement
A road of exactly 100 miles is divided into N consecutive segments, each with a length and a posted speed limit. Bessie drives the full 100 miles, broken into M consecutive segments each with a length and her actual speed. Output the maximum amount, over all positions along the road, by which her actual speed exceeds the posted limit (0 if she never speeds).
Constraints
- 1 ≤ N, M ≤ 100.
- All lengths and speeds are positive integers; lengths sum to exactly 100.
- Speeds and limits are between 1 and 100.
- Time limit: 2s. Memory limit: 256 MB.
Key idea
Expand both segmentations into per-mile arrays of length 100: limit[i] for mile i from the road's segmentation, speed[i] for mile i from Bessie's segmentation. Then the answer is maxi(speed[i] − limit[i], 0). With only 100 miles the unrolling is free.
Complexity target
O(100) — both expansion and scan.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, M; cin >> N >> M;
int limit[100] = {0}, speed[100] = {0};
int pos = 0;
for (int i = 0; i < N; ++i) {
int len, lim; cin >> len >> lim;
for (int k = 0; k < len; ++k) limit[pos++] = lim;
}
pos = 0;
for (int i = 0; i < M; ++i) {
int len, sp; cin >> len >> sp;
for (int k = 0; k < len; ++k) speed[pos++] = sp;
}
int ans = 0;
for (int i = 0; i < 100; ++i) ans = max(ans, speed[i] - limit[i]);
cout << ans << "\n";
}
Pitfalls
- The two segmentations are independent. A boundary in Bessie's segments does not align with road-limit boundaries.
- Mile granularity is enough. Lengths are integer miles summing to 100 — no fractional positions to worry about.
- Answer is 0, not negative. If she's always slower than the limit, output 0.
- Sum-of-lengths must equal 100. If your expansion pointer overflows 100, you misread input.
Problem 3 — Contaminated Milk
Statement
There are N people and M milk types. You're given D drinking records (person, milk, time) and S sick reports (person, time). Exactly one milk type is contaminated, and it has been contaminated since time 0. A person gets sick at most once. A person can be the cause of "sick" only if they drank the contaminated milk strictly before their sick time. You must report the maximum number of people who could ultimately get sick — namely, over every milk type that is consistent with the sick reports (every sick person drank it before they got sick), the total number of people who drank that milk at any time. Take the maximum.
Constraints
- 1 ≤ N, M ≤ 50.
- 1 ≤ D ≤ 1000, 0 ≤ S ≤ N.
- Times are integers in [1, 100].
- Time limit: 2s. Memory limit: 256 MB.
Key idea
For each candidate milk type m: check that every sick person p has at least one drinking record of m with time < sick_time(p). If so, count the number of distinct people who ever drank m at any time — each of them could eventually get sick. Output the maximum such count over all valid m.
Complexity target
O(M · (D + N)) which is trivially small.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int N, M, D, S; cin >> N >> M >> D >> S;
// drink[m] = list of (person, time); drinkers[m] = set of people who ever drank m.
vector<vector<pair<int,int>>> drink(M + 1);
vector<set<int>> drinkers(M + 1);
for (int i = 0; i < D; ++i) {
int p, m, t; cin >> p >> m >> t;
drink[m].push_back({p, t});
drinkers[m].insert(p);
}
vector<pair<int,int>> sick(S); // (person, time)
for (auto& s : sick) cin >> s.first >> s.second;
int ans = 0;
for (int m = 1; m <= M; ++m) {
bool ok = true;
for (auto [p, t] : sick) {
bool found = false;
for (auto [pp, tt] : drink[m]) if (pp == p && tt < t) { found = true; break; }
if (!found) { ok = false; break; }
}
if (ok) ans = max(ans, (int)drinkers[m].size());
}
cout << ans << "\n";
}
Pitfalls
- "Before" is strict. A sick person must have drunk the milk at a time strictly less than their sick time.
- Counting distinct drinkers, not records. Use a set per milk — one person drinking twice is still one person.
- Some milks may be impossible. Skip those; the answer is over valid milks only.
- S can be 0. Then every milk is valid; the answer is the milk with the most distinct drinkers (could be 0 if no one drank).
What Bronze December 2015 was actually testing
- P1 — interval union. Either inclusion–exclusion or a tiny boolean array; both are 5-line solutions.
- P2 — segmentation overlay. Expand into per-mile arrays so the two segmentations no longer have to align.
- P3 — hypothesis enumeration. Brute-force the contaminated milk; check consistency with sick reports; count drinkers.