USACO 2016 US Open · Bronze · all three problems
Problem 1 — Diamond Collector
Statement
Bessie has N diamonds with integer sizes s1, …, sN. She wants to display diamonds in a single case but only if the largest and smallest displayed diamond differ by at most K in size. Choose a subset of the diamonds satisfying this rule and output the maximum size of that subset.
Constraints
- 1 ≤ N ≤ 1000.
- 0 ≤ K ≤ 109.
- 0 ≤ si ≤ 109.
- Time limit: 2s.
Key idea
Sort sizes ascending. The optimal subset is then a contiguous range in the sorted array (any non-contiguous skip can only reduce the count without helping the spread). Use a two-pointer / sliding window: for each left index i, advance j while s[j] − s[i] ≤ K, and track max(j − i + 1).
Complexity target
O(N log N) for the sort, O(N) for the sweep. With N ≤ 1000 even O(N2) passes easily.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int N; long long K;
cin >> N >> K;
vector<long long> s(N);
for (auto& x : s) cin >> x;
sort(s.begin(), s.end());
int best = 0, j = 0;
for (int i = 0; i < N; ++i) {
if (j < i) j = i;
while (j < N && s[j] - s[i] <= K) ++j;
best = max(best, j - i);
}
cout << best << "\n";
}
Pitfalls
- Sort first. The "contiguous range after sorting" reduction is the whole trick. Without sorting, a brute force is O(2N).
- Inclusive spread. The condition is max − min ≤ K, not strictly less than. Off-by-one here will lose sample points.
- Use 64-bit. Sizes and K go up to 109; differences fit in 32-bit but read into
long longto avoid mental overhead.
Problem 2 — Bull in a China Shop
Statement
A bull starts at a known cell in a small N×N grid. In one "move" the bull walks in any of the 8 compass directions (N, NE, E, SE, S, SW, W, NW) some positive number of cells, stopping whenever it likes (i.e. each move is a queen-like ray of any positive length within the grid). After exactly K moves, how many distinct cells could the bull occupy?
Constraints
- 1 ≤ N ≤ 10.
- 1 ≤ K ≤ 8 (Bronze keeps the move budget tiny).
- Time limit: 2s.
Key idea
Brute-force BFS / DFS where the state is (row, col, moves used). From each cell, enumerate the 8 directions and every positive step length that stays on the grid. Track visited (r, c, k); at the end, count cells (r, c) that were ever visited with exactly k = K. Because N ≤ 10 and K is tiny, the state space is ≤ 10×10×K and the per-state branching is bounded by 8×9 = 72.
Complexity target
O(N2 · K · 8N) ≤ a few thousand operations.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int N, K;
int dr[8] = {-1,-1,0,1,1, 1, 0,-1};
int dc[8] = { 0, 1,1,1,0,-1,-1,-1};
bool vis[12][12][10];
void dfs(int r, int c, int k) {
if (vis[r][c][k]) return;
vis[r][c][k] = true;
if (k == K) return;
for (int d = 0; d < 8; ++d)
for (int step = 1; ; ++step) {
int nr = r + dr[d]*step, nc = c + dc[d]*step;
if (nr < 0 || nr >= N || nc < 0 || nc >= N) break;
dfs(nr, nc, k + 1);
}
}
int main() {
int sr, sc;
cin >> N >> K >> sr >> sc;
dfs(sr, sc, 0);
int ans = 0;
for (int r = 0; r < N; ++r)
for (int c = 0; c < N; ++c)
if (vis[r][c][K]) ++ans;
cout << ans << "\n";
}
Pitfalls
- "Exactly K moves," not "at most K". A cell reachable in K−1 moves doesn't count unless it's also reachable in K. Memoize the move count separately.
- Each move has positive length. Stepping zero cells is not a move; don't allow it or you collapse the answer.
- 1-indexed input. Check whether the start coordinates in the input are 0- or 1-indexed and convert once at read time.
Problem 3 — Field Reduction
Statement
FJ has N cows at integer positions (xi, yi). The "field" is the smallest axis-aligned bounding rectangle that contains all cows; its area is (max x − min x) · (max y − min y). Remove exactly 3 cows so the bounding-box area of the remaining N−3 cows is minimized. Output the minimum area.
Constraints
- 4 ≤ N ≤ 50 000.
- 1 ≤ xi, yi ≤ 40 000.
- Time limit: 2s.
Key idea
The minimum bounding box after removal only depends on the four extremes — the cows with min x, max x, min y, max y. To reduce the box, one of the removed cows must be one of these four "extreme" cows. So the candidate set of removable cows is at most the 4 cows holding the four extremes — plus, to be safe, a few more cows holding the next-best extremes (top-3 smallest x, top-3 largest x, top-3 smallest y, top-3 largest y — at most 12 distinct cows). Try every 3-subset of those ≤ 12 candidates; for each, recompute the bounding box on the remaining cows and take the minimum.
Complexity target
O(N) to pick candidate sets, O(C(12,3) · N) ≤ 220 N to evaluate. About 107.
Reference solution (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int N; cin >> N;
vector<int> X(N), Y(N);
for (int i = 0; i < N; ++i) cin >> X[i] >> Y[i];
auto topK = [&](auto cmp) {
vector<int> idx(N); iota(idx.begin(), idx.end(), 0);
partial_sort(idx.begin(), idx.begin()+3, idx.end(), cmp);
return vector<int>(idx.begin(), idx.begin()+3);
};
set<int> cand;
for (int i : topK([&](int a, int b){ return X[a] < X[b]; })) cand.insert(i);
for (int i : topK([&](int a, int b){ return X[a] > X[b]; })) cand.insert(i);
for (int i : topK([&](int a, int b){ return Y[a] < Y[b]; })) cand.insert(i);
for (int i : topK([&](int a, int b){ return Y[a] > Y[b]; })) cand.insert(i);
vector<int> c(cand.begin(), cand.end());
long long ans = LLONG_MAX;
int M = c.size();
for (int a = 0; a < M; ++a)
for (int b = a+1; b < M; ++b)
for (int d = b+1; d < M; ++d) {
set<int> skip = {c[a], c[b], c[d]};
int xl = INT_MAX, xh = INT_MIN, yl = INT_MAX, yh = INT_MIN;
for (int i = 0; i < N; ++i) if (!skip.count(i)) {
xl = min(xl, X[i]); xh = max(xh, X[i]);
yl = min(yl, Y[i]); yh = max(yh, Y[i]);
}
ans = min(ans, (long long)(xh-xl)*(yh-yl));
}
cout << ans << "\n";
}
Pitfalls
- Why "top 3" per axis? If you remove only the single most extreme cow on one axis, the new extreme is the 2nd; if you remove 2, it's the 3rd. Three removals total × one axis ⇒ you need up to 3 candidates per direction.
- Use indices, not values. Two cows can share an extreme x; you remove cows, not coordinates. De-duplicate by index, not by (x, y).
- Brute O(N3) TLEs. With N = 50 000, you cannot iterate over all triples of cows. The candidate-set reduction is the contest's whole point.
What Bronze 2016 US Open was actually testing
- P1 — sort + sliding window. The canonical Bronze "Diamond" pattern; recognize that sorting linearizes the optimal subset.
- P2 — bounded brute force with the right state. When N ≤ 10, the answer is to enumerate — but enumerate the right state.
- P3 — candidate-set pruning. A real-world Silver-flavored trick: identify the ≤ 12 cows that could possibly be removed before you brute-force the triples.