2023 January Bronze — three problems
← 2023 January contest index · Official results page
Bronze 2023-Jan is two ad-hoc / counting problems and one greedy. The dominant skill is reading carefully and indexing without off-by-ones.
Problem 1 · Leaders
Official statement (cpid=1281)
Statement (paraphrased)
There are N cows in a row, each cow has a breed (G for Guernsey, H for Holstein) and points to another cow of the same breed (or to itself). A cow x is a leader of its breed if every cow of the same breed lies in the range [x, p(x)] where p(x) is the cow x points to, and x is the leftmost cow of its breed in that range. Count ordered pairs (a, b) of leaders of different breeds such that the intervals [a, p(a)] and [b, p(b)] touch — i.e. one is the leftmost cow of its breed and the other lies in the first's interval.
Constraints
- 1 ≤ N ≤ 105
- Each cow points to one cow (1-indexed) of the same breed
- Time/memory: USACO Bronze default (2 s / 256 MB)
Key idea
There are at most one G-leader and one H-leader, because a leader's interval must cover every cow of its breed and start at the leftmost such cow. So compute (a) the leftmost G and the leftmost H, (b) check whether the leftmost-of-breed-X is a valid leader (its pointer reaches the last cow of breed X and that cow points back inside its interval). Then test the two pairing cases.
Concretely: find leftmost G index gL and rightmost G index gR; G has a leader iff cow[gL].p ≥ gR and cow at position cow[gL].p has breed G. Same for H. Count the at-most-two valid leader pairs by the touching rule.
Complexity
O(N) per test case.
C++ reference
#include <bits/stdc++.h>
using namespace std;
int main() {
int N; scanf("%d", &N);
string s; s.resize(N);
for (int i = 0; i < N; i++) { char c; scanf(" %c", &c); s[i] = c; }
vector<int> p(N);
for (int i = 0; i < N; i++) { scanf("%d", &p[i]); --p[i]; }
auto findLeader = [&](char breed) -> int {
int lo = -1, hi = -1;
for (int i = 0; i < N; i++) if (s[i] == breed) { if (lo < 0) lo = i; hi = i; }
if (lo < 0) return -1;
// leader candidate is lo; needs p[lo] >= hi and s[p[lo]] == breed
if (p[lo] >= hi && s[p[lo]] == breed) return lo;
return -1;
};
int lg = findLeader('G'), lh = findLeader('H');
int ans = 0;
// pair (G-leader, H-leader): H must be the leftmost H AND lie in G's interval, or vice versa
auto check = [&](int a, int b) {
if (a < 0 || b < 0) return false;
return (a <= b && b <= p[a]) || (b <= a && a <= p[b]);
};
if (check(lg, lh)) ans++;
printf("%d\n", ans); // [verify] exact "pair" definition against editorial cpid=1281
}
Pitfalls
- Mis-identifying a leader: the leader's own pointer p(x) must reach the rightmost cow of the breed, not just be ≥ x.
- Off-by-one when the leader points to itself (single-cow breed).
- The "touching" rule is order-sensitive — re-read the PDF to confirm whether (a,b) and (b,a) count separately.
Problem 2 · Air Cownditioning II
Official statement (cpid=1282)
Statement (paraphrased)
N stalls each have a required cooling demand di. M air conditioners are available; the i-th AC covers stalls [si, ti] adding pi cooling to each stall in its range, and costs mi dollars to buy. Choose a subset of ACs so every stall's total cooling is at least di, minimising total cost. Bronze: M ≤ 10, so 2M subset enumeration is fine.
Constraints
- 1 ≤ N ≤ 100, 1 ≤ M ≤ 10
- 1 ≤ di, pi, mi ≤ 106
- Time/memory: USACO Bronze default (2 s / 256 MB)
Key idea
Enumerate all 2M ≤ 1024 subsets. For each subset, sum cooling per stall (cheap: 100·10 work) and check every stall is satisfied. Track the minimum cost.
Complexity
O(2M · N · M) ≈ 106.
C++ reference
#include <bits/stdc++.h>
using namespace std;
int main() {
int N, M; scanf("%d %d", &N, &M);
vector<int> d(N + 2, 0);
for (int i = 1; i <= N; i++) scanf("%d", &d[i]);
vector<int> s(M), t(M), p(M), m(M);
for (int i = 0; i < M; i++) scanf("%d %d %d %d", &s[i], &t[i], &p[i], &m[i]);
int best = INT_MAX;
for (int mask = 0; mask < (1 << M); mask++) {
vector<long long> cool(N + 2, 0);
long long cost = 0;
for (int i = 0; i < M; i++) if (mask >> i & 1) {
cost += m[i];
for (int j = s[i]; j <= t[i]; j++) cool[j] += p[i];
}
bool ok = true;
for (int j = 1; j <= N; j++) if (cool[j] < d[j]) { ok = false; break; }
if (ok && cost < best) best = (int)cost;
}
printf("%d\n", best);
}
Pitfalls
- Reading the input order — Bronze sometimes lists (s, t, p, m) with cost last; double-check the PDF.
- "At least" not "exactly" — extra cooling is fine.
- Some stalls have demand 0 (or N indices are 1-based vs 0-based depending on the PDF).
Problem 3 · Moo Operations
Official statement (cpid=1283)
Statement (paraphrased)
Given a string S over {M, O, F} (or similar small alphabet),
the allowed operations are: change one character (cost 1), or delete a character from either end (cost 1).
Find the minimum number of operations to turn S into a string of the form MOOMOO...MOO (some
number of MOO repetitions, possibly zero). Multiple test cases per input.
Constraints
- |S| ≤ 100, up to 10 test cases
- Time/memory: USACO Bronze default (2 s / 256 MB)
Key idea
The target length must be a multiple of 3 and at most |S| (since we can only delete, never insert). For each candidate target length 3k from 0 to ⌊|S|/3⌋·3, and each starting position i in S of length 3k, count mismatches with the pattern "MOOMOO..."; the cost is (|S| − 3k) deletions + mismatch count. Take the minimum.
Complexity
O(|S|2) per test case — fine for |S| ≤ 100.
C++ reference
#include <bits/stdc++.h>
using namespace std;
int main() {
int T; scanf("%d", &T);
while (T--) {
char buf[256]; scanf("%s", buf);
string s = buf;
int n = (int)s.size();
const string pat = "MOO";
int best = n; // worst case: delete everything (target = empty string)
for (int k = 3; k <= n; k += 3) {
for (int i = 0; i + k <= n; i++) {
int mismatch = 0;
for (int j = 0; j < k; j++)
if (s[i + j] != pat[j % 3]) mismatch++;
int cost = (n - k) + mismatch;
best = min(best, cost);
}
}
printf("%d\n", best);
}
}
Pitfalls
- Don't forget the empty-target option (cost = |S|).
- Deletions are only from either end, not the middle — that's why we slide a window of length 3k.
- The alphabet may include letters that don't appear in
MOO; substitution still costs 1 per character.