USACO2022美国公开赛金牌组问题1. Apple Catching

It's raining apples! At certain points in time, some number of apples will hit the number line. At certain points in time, some of Farmer John's cows will arrive on the number line and start catching apples.

If an apple hits the number line without a cow to catch it, it is lost forever. If a cow and an apple arrive at the same time, the cow catches it. Each cow can travel one unit per second. Once a cow catches a single apple, she exits the number line.

If FJ's cows collaborate optimally, how many apples can they catch in total?

INPUT FORMAT (input arrives from the terminal / stdin):
The first line contains N (1≤N≤2⋅105), the number of times apples hit the number line or FJ's cows appear.
The next N lines each contain four integers qi, ti, xi, and ni (qi∈{1,2},0≤ti≤109,0≤xi≤10^9,1≤ni≤10^3).

If qi=1, this means that ni of FJ's cows arrive on the number line at time ti at location xi.
If qi=2, this means that ni apples will hit the number line at time ti at location xi.
It is guaranteed that all of the ordered pairs (ti,xi) are distinct.

OUTPUT FORMAT (print output to the terminal / stdout):
The maximum number of apples FJ's cows may collectively catch.
SAMPLE INPUT:
5
2 5 10 100
2 6 0 3
2 8 10 7
1 2 4 5
1 4 7 6
SAMPLE OUTPUT:
10
In this example, none of the 100 apples that land at time t=5 may be caught. Here is a way for 10 apples to be caught:

All six of FJ's cows that arrive at time t=4 catch one of the apples that land at time t=8.
One of FJ's cows that arrive at time t=2 catches one of the apples that land at time t=8.
Three of the remaining cows that arrive at time t=2 catch one of the apples that land at time t=6.
SAMPLE INPUT:
5
2 5 10 100
2 6 0 3
2 8 11 7
1 2 4 5
1 4 7 6
SAMPLE OUTPUT:
9
Here again, none of the apples that land at time t=5 may be caught. Furthermore, none of the cows that arrive at time t=2 may catch any of the apples that land at time t=8. Here is a way for 9 apples to be caught:

All six of FJ's cows that arrive at time t=4 catch one of the apples that land at time t=8.
Three of the remaining cows that arrive at time t=2 catch one of the apples that land at time t=6.
Problem credits: Benjamin Qi

USACO2022美国公开赛金牌组问题三—解决方案

(Analysis by Danny Mittal)
We will refer to the string of Us and Ds as s.

Subtask 1: N≤500

We can do DP. For each triple (j,k,u), our DP says whether there exists a subsequence of p1,…,pk consistent with s1…sj that ends in the number u. Transitions are constant time, so the runtime is O(N3).

Subtask 2: N≤5000

We can improve the DP from the previous subtask by noting that depending on whether sj+1 is U or D, it's optimal for the previous number in the subsequence to be as small or as large as possible. Therefore, our DP should find for each pair (j,k) both the smallest and the largest numbers such that there exists a subsequence of p1,…,pk consistent with s1…sj that ends in that number. Transitions are again constant time, so the runtime is O(N2).

Subtask 3: s is Us followed by Ds

Apply a standard LIS algorithm to find for each number the longest LIS ending in that number, as well as the longest LIS ending in that number that goes in reverse (starting from the end of p). Now let the number of Us in s be j. If there is no LIS of p with j+1, then we simply use the longest LIS that we found. Otherwise, find the first position in p where we have an LIS of length j+1, then use the longest reverse LIS that ends at or after that position to compute the answer.

The runtime is O(NlgN) using an appropriate LIS algorithm.

Subtask 4: No additional constraints

Intuitively, it makes sense for us to try to find the fastest (ending the earliest) subsequence of p consistent with each prefix of s, and build on that subsequence to find the fastest subsequence for the next prefix of s. Unfortunately, this idea doesn't even work for normal LIS (longest increasing subsequence), i. e. the case where s is UUUU..., because we can have a case like

p=[5,6,7,1,2,3,4]

where the fastest increasing subsequence of length 3 is [5,6,7], but the fastest one of length 4 is [1,2,3,4] which doesn't build on [5,6,7] at all.

However, it turns out that we can actually apply this idea when switching from contiguous segments of U to contiguous segments of D and vice versa. Specifically, suppose that sj is D, and the next x letters in s are U. If the fastest subsequence a of p consistent with s1…sj ends at index k, then consider finding the fastest LIS b of length x+1 in p considering only positions from k onwards. Say that b ends at position k′.

It's clear that the fastest subsequence of p consistent with s1…sj+x must end at or after position k′, because clearly it's not possible to find a subsequence consistent with s1…sj then an LIS of length x+1 that starts with the previous subsequence prior to k′.

However, we can actually use a and b to create a subsequence consistent with s1…sj+x that ends at position k′. If the last number aj in a and the first number b0 in b are the same, then we're done, because we can simply attach them at that number. Otherwise, note that it can't be that aj<b0, because otherwise we could add aj to the beginning of b and remove b's last element to get an LIS of length x+1 that ends earlier. Therefore, it must be that aj>b0. However, since sj is D, we can actually take a, remove aj, then add on b0, which is valid because aj−1>aj>b1 so the D is still satisfied, and now use b0 to glue together a and b.

Therefore, the end position of the fastest subsequence of p consistent with s1…sj+x is simply the end position of the fastest LIS of p considering only positions starting from the end position of the fastest subsequence consistent with s1…sj. All of this also applies when U and D are switched.

This means that our algorithm can work as follows. We divide s into its contiguous segments of U and D, and for each segment find the fastest LIS or LDS of the length of the segment +1 that only considers the part of p starting (inclusive) from the end of the previous LDS or LIS. We finish when we are unable to find an LIS or LDS of the appropriate length for some segment and simply use the longest one we were able to find for that last segment to compute the answer.

To find LISs and LDSs, we can simply apply one of the standard algorithms for finding LIS, but we have to be careful that the algorithm we use runs in time a function of the number of elements we consider, not a function of N, as there can potentially be many segments in s. An elegant choice given this constraint is the binary search tree algorithm for LIS, which is used in the Java code below.

Assuming our LIS algorithm runs in O(xlgx) where x is the number of elements we consider, the runtime of our overall algorithm is O(NlgN).

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class UpDownSubsequence {

public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(in.readLine());
StringTokenizer tokenizer = new StringTokenizer(in.readLine());
char[] directions = in.readLine().toCharArray();
int k = 0;
int last = Integer.parseInt(tokenizer.nextToken());
while (tokenizer.hasMoreTokens() && k < directions.length) {
char direction = directions[k];
TreeSet<Integer> treeSet = new TreeSet<Integer>(direction == 'U' ? Comparator.naturalOrder() : Comparator.reverseOrder());
treeSet.add(last);
while (tokenizer.hasMoreTokens() && k < directions.length && directions[k] == direction) {
last = Integer.parseInt(tokenizer.nextToken());
Integer displaced = treeSet.higher(last);
if (displaced == null) {
k++;
} else {
treeSet.remove(displaced);
}
treeSet.add(last);
}
}
System.out.println(k);
}
}

USACO2022美国公开赛金牌组问题三——Up Down Subsequence

Farmer John's N cows (2≤N≤3⋅105), conveniently numbered 1…N as usual, have ordered themselves according to a permutation p1,p2,…,pN of 1…N. You are also given a string of length N−1 consisting of the letters U and D. Please find the maximum K≤N−1 such that there exists a subsequence a0,a1,…,aK of p such that for all 1≤j≤K, aj−1<aj if the jth letter in the string is U, and aj−1>aj if the jth letter in the string is D.

INPUT FORMAT (input arrives from the terminal / stdin):
The first line contains N.
The second line contains p1,p2,…,pN.

The last line contains the string.

OUTPUT FORMAT (print output to the terminal / stdout):
Write out maximum possible value of K.
SAMPLE INPUT:
5
1 5 3 4 2
UDUD
SAMPLE OUTPUT:
4
We can choose [a0,a1,a2,a3,a4]=[p1,p2,p3,p4,p5]; the entire permutation is consistent with the string.

SAMPLE INPUT:
5
1 5 3 4 2
UUDD
SAMPLE OUTPUT:
3
We can choose [a0,a1,a2,a3]=[p1,p3,p4,p5].

SCORING:
Test cases 3-4 satisfy N≤500.
Test cases 5-8 satisfy N≤5000.
In test cases 9-12, the string consists of Us followed by Ds.
Test cases 13-22 satisfy no additional constraints.
Problem credits: Danny Mittal

USACO2022美国公开赛白金组问题二—解决方案

(Analysis by Danny Mittal)
Subtask 1: N≤100, M≤200
We can solve this subtask by creating a new graph of pairs of nodes from the old graph, where each pair (a,b) represents a game state where one token is on a and one token is on b. We can perform a search where we repeatedly remove nodes that are winning for the brain.
In order to do this, we maintain for each pair (a,b) the amount of remaining pairs (c,b) such that a→c is an edge in the original graph, and a similar amount of remaining pairs (a,c). In the process of removing pairs, if one of these amounts becomes 0 for a certain pair (a,b), then the brain can choose that token in order to win, so we remove (a,b) as well, then decrement the amounts for the appropriate other pairs by looking at incoming edges to a and b.
At the end of this process, any remaining pairs represent game states from which the brain cannot win. We can then answer queries by simply checking whether they are a pair that was removed or not.
The bottleneck in this algorithm is the part after removing a pair when we decrement the other appropriate pairs' amounts. Each edge a→c is potentially considered as part of pairs (c,b) and (b,c) for all b, making the worst case runtime O(N) per edge and so O(NM) overall. This is far under the time limit, so less efficient variants of this solution could also have passed.
Subtask 2: N≤5000
First note that if a node with a token on it has no outgoing edges, then the brain can win by simply choosing the token on that node to leave the hoof without any moves. This means that we can mark the nodes as such and then simply remove them from the graph. Furthermore, any nodes that now have no outgoing edges also represent a win for the brain, because the brain can repeatedly choose the token on those nodes, and eventually the token will reach a node with no outgoing edges. Therefore, we can repeatedly remove all nodes with no outgoing edges from the graph until all nodes remaining have at least one outgoing edge.
Now, consider a node a with only a single outgoing edge to a different node b. Any token on a can clearly be moved to b. This means that we don't need to really consider a as being separate from b; if the brain can force the hoof to lose by making it so that both tokens would end up at a, the brain can also just force the hoof to lose by making it so that both tokens would end up at b, by making each token move once more. Therefore, we can "merge" a into b, meaning that b inherits all of a's incoming edges. Then, just like before, some new nodes may now have only one outgoing edge because they previously had edges only to a and b, so we can merge those as well. At the end of this process, all nodes remaining in the graph will either have at least two outgoing edges, or a single edge to themself.
We now make the critical observation that in a graph where every node has at least two outgoing edges, if the tokens start at different nodes, then no matter which token the brain picks each time, the hoof always has a valid node to move it into that isn't the location of the other node, and so the hoof always wins. This extends to graphs that also have nodes with only a single edge to themselves, because the hoof can just move the token across that single edge back to the same node, since the other token is at a different node.
Therefore, after applying the above two reductions, we can answer a query for starting nodes a and b as follows:
If either a or b was removed from the graph in the first reduction, then the brain wins. Otherwise, if a and b became the same node after the merging process in the second reduction, the brain still wins. Otherwise, the hoof wins.
The two above reductions can be done fairly straightforwardly in O(N2) by maintaining a set of incoming edges and a set of outgoing edges for each node, then using DFS or BFS. Each query is answered in constant time, for an overall runtime of O(N2+Q).
Subtask 3: No additional constraints
The first reduction should actually already run in linear time if you use sets as suggested above. To improve the runtime of the second reduction, we can use small to large merging and union find. When we merge a into b, instead of simply adding all of a's incoming edges to b's, we add whichever set is smaller to whichever set is larger. This means that each edge is added to a set at most lgN times. We then use union find to keep track of which node each node has been merged into. Whenever we find a node a to merge into a node b, we need to make sure to instead merge the union find root of a into the union find root of b.
As each edge is merged at most lgN times, the overall runtime becomes O(MlgN+Q).
Java code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
public class HoofAndBrain {
static int[] union;
static int find(int u) {
if (union[u] != union[union[u]]) {
union[u] = find(union[u]);
}
return union[u];
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer tokenizer = new StringTokenizer(in.readLine());
int n = Integer.parseInt(tokenizer.nextToken());
int m = Integer.parseInt(tokenizer.nextToken());
Set<Integer>[] adj = new Set[n + 1];
Set<Integer>[] rev = new Set[n + 1];
union = new int[n + 1];
for (int a = 1; a <= n; a++) {
adj[a] = new HashSet<>();
rev[a] = new HashSet<>();
union[a] = a;
}
for (; m > 0; m--) {
tokenizer = new StringTokenizer(in.readLine());
int a = Integer.parseInt(tokenizer.nextToken());
int b = Integer.parseInt(tokenizer.nextToken());
adj[a].add(b);
rev[b].add(a);
}
Stack<Integer> stack = new Stack<>();
for (int a = 1; a <= n; a++) {
if (adj[a].isEmpty()) {
stack.push(a);
}
}
while (!stack.isEmpty()) {
int a = stack.pop();
union[a] = 0;
for (int b : rev[a]) {
adj[b].remove(a);
if (adj[b].isEmpty()) {
stack.push(b);
}
}
}
for (int a = 1; a <= n; a++) {
if (adj[a].size() == 1) {
stack.push(a);
}
}
while (!stack.isEmpty()) {
int a = stack.pop();
int c = 0;
for (int b : adj[a]) {
c = b;
}
a = find(a);
c = find(c);
if (a != c) {
if (rev[a].size() > rev[c].size()) {
int temp = a;
a = c;
c = temp;
}
for (int b : rev[a]) {
adj[b].remove(a);
adj[b].add(c);
if (adj[b].size() == 1) {
rev[c].remove(b);
stack.push(b);
} else {
rev[c].add(b);
}
}
union[a] = c;
}
}
StringBuilder out = new StringBuilder();
for (int q = Integer.parseInt(in.readLine()); q > 0; q--) {
tokenizer = new StringTokenizer(in.readLine());
int a = Integer.parseInt(tokenizer.nextToken());
int b = Integer.parseInt(tokenizer.nextToken());
int u = find(a);
int v = find(b);
if (u == 0 || v == 0 || u == v) {
out.append('B');
} else {
out.append('H');
}
}
System.out.println(out);
}
}
Exercise: Solve the problem where the hoof wins by not having a valid move, and the brain wins by the game continuing indefinitely.

USACO2022美国公开赛白金组问题 2——Hoof and Brain

Given a directed graph with N vertices and M edges (2≤N≤10^5, 1≤M≤2·10^5), Farmer John's cows like to play the following game with two players.
Place two tokens on distinct nodes in the graph. Each turn, one player, the brain, will choose a token that must be moved along an outgoing edge. The other player, the hoof, will choose which edge to move the token along. The two tokens can never be on the same node. If at some point the hoof can't make a valid move, the brain wins. If the game continues indefinitely, the hoof wins.
You are given Q queries (1≤Q≤10^5) indicating the starting nodes of the two tokens. For each query, output which player will win.
INPUT FORMAT (input arrives from the terminal / stdin):
The first line contains N and M.
The next M lines each contain two integers a and b, denoting an edge from a to b.
The graph does not contain self-loops or multiple edges.
The next line contains Q.
The final Q lines each contain two integers x and y satisfying 1≤x,y≤N and x≠y, indicating the starting nodes of the tokens.
OUTPUT FORMAT (print output to the terminal / stdout):
A string of length Q, where each character is B for the brain winning and H for the hoof winning.
**Note: the time limit for this problem is 4s, twice the default.**
SAMPLE INPUT:
9 10
1 2
2 3
3 4
4 7
3 5
1 6
6 8
8 9
9 6
7 2
4
1 5
1 2
1 6
2 4
SAMPLE OUTPUT:
BHHB
The brain can win the first game by selecting node 5; then the hoof has no valid move.
The brain can win the last game by selecting node 4 and then node 7; then the hoof has no valid move.
The hoof wins the other games.
SCORING:
Test cases 2-3 satisfy N≤100, M≤200.
Test cases 4-9 satisfy N≤5000.
Test cases 10-21 satisfy no additional constraints.
Problem credits: Danny Mittal

USACO2022美国公开赛白金组问题一解决方案

(Analysis by Benjamin Qi)
I will refer to contiguous sequences as intervals. Define the value of an interval to be the minimum possible final number it can be converted into.
Subtask 1: Similar to 248, we can apply dynamic programming on ranges. Specifically, if dp[i][j] denotes the value of interval i…j, then
dp[i][j]={Aaimini≤k<jmax(dp[i][k],dp[k+1][j])+1i=ji<j.
The time complexity is O(N3).
#include <bits/stdc++.h>
using namespace std;
template <class T> using V = vector<T>;
#define all(x) begin(x), end(x)
template <class T> void ckmin(T &a, const T &b) { a = min(a, b); }
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
V<int> A(N);
for (int &x : A) cin >> x;
V<V<int>> dp(N, V<int>(N));
for (int i = N - 1; i >= 0; --i) {
dp.at(i).at(i) = A.at(i);
for (int j = i + 1; j < N; ++j) {
dp[i][j] = INT_MAX;
for (int k = i; k < j; ++k) {
ckmin(dp.at(i).at(j),
max(dp.at(i).at(k), dp.at(k + 1).at(j)) + 1);
}
}
}
int64_t ans = 0;
for (int i = 0; i < N; ++i) {
for (int j = i; j < N; ++j) {
ans += dp.at(i).at(j);
}
}
cout << ans << "\n";
}
Subtask 2: We can optimize the solution above by more quickly finding the maximum k′ such that dp[i][k′]≤dp[k′+1][j]. Then we only need to consider k∈{k′,k′+1} when computing dp[i][j]. Using the observation that k′ does not decrease as j increases and i is held fixed leads to a solution in O(N2):
#include <bits/stdc++.h>
using namespace std;
template <class T> using V = vector<T>;
#define all(x) begin(x), end(x)
template <class T> void ckmin(T &a, const T &b) { a = min(a, b); }
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
V<int> A(N);
for (int &x : A) cin >> x;
V<V<int>> dp(N, V<int>(N));
for (int i = N - 1; i >= 0; --i) {
dp.at(i).at(i) = A.at(i);
int k = i - 1;
for (int j = i + 1; j < N; ++j) {
while (k + 1 < j && dp.at(i).at(k + 1) <= dp.at(k + 2).at(j)) ++k;
dp[i][j] = INT_MAX;
ckmin(dp[i][j], dp.at(k + 1).at(j));
ckmin(dp[i][j], dp.at(i).at(k + 1));
++dp[i][j];
}
}
int64_t ans = 0;
for (int i = 0; i < N; ++i) {
for (int j = i; j < N; ++j) {
ans += dp.at(i).at(j);
}
}
cout << ans << "\n";
}
Alternatively, finding k′ with binary search leads to a solution in O(N2logN).
Subtask 3: Similar to 262144, we can use binary lifting.
For each of v=1,2,3,…, I count the number of intervals with value at least v. The answer is the sum of this quantity over all v.
#include <bits/stdc++.h>
using namespace std;
template <class T> using V = vector<T>;
#define all(x) begin(x), end(x)
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
V<int> A(N);
for (int &x : A) cin >> x;
V<V<int>> with_val;
for (int i = 0; i < N; ++i) {
while (size(with_val) <= A[i]) with_val.emplace_back();
with_val.at(A[i]).push_back(i);
}
V<int> nex(N + 1);
iota(all(nex), 0);
int64_t ans = 0;
for (int v = 1;; ++v) {
if (nex[0] == N) {
cout << ans << "\n";
exit(0);
}
// add all intervals with value >= v
for (int i = 0; i <= N; ++i) ans += N - nex[i];
for (int i = 0; i <= N; ++i) nex[i] = nex[nex[i]];
if (v < size(with_val)) {
for (int i : with_val.at(v)) {
nex[i] = i + 1;
}
}
}
}
Subtask 4: For each i from 1 to N in increasing order, consider the values of all intervals with right endpoint i. Note that the value v of each such interval must satisfy v∈[Ai,Ai+?log2i?] due to A being sorted. Thus, it suffices to be able to compute for each v the minimum l such that dp[l][i]≤v. To do this, we maintain a partition of 1…i into contiguous subsequences such that every contiguous subsequence has value at most Ai and is leftwards-maximal (extending any subsequence one element to the left would cause its value to exceed Ai). When transitioning from i?1 to i, we merge every two consecutive contiguous subsequences Ai?Ai?1 times and then add contiguous subsequence [i,i] to the end of the partition.
#include <bits/stdc++.h>
using namespace std;
template <class T> using V = vector<T>;
#define all(x) begin(x), end(x)
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
vector<int> A(N);
for (int &x : A) cin >> x;
assert(is_sorted(all(A)));
// left endpoints of each partition interval in decreasing order
deque<int> left_ends;
int64_t ans = 0;
for (int i = 0; i < N; ++i) {
if (i) {
for (int v = A[i - 1]; v < A[i]; ++v) {
if (size(left_ends) == 1) break;
// merge every two consecutive intervals in partition
deque<int> n_left_ends;
for (int j = 0; j < (int)size(left_ends); ++j) {
if ((j & 1) || j + 1 == (int)size(left_ends)) {
n_left_ends.push_back(left_ends[j]);
}
}
swap(left_ends, n_left_ends);
}
}
left_ends.push_front(i); // add [i,i] to partition
int L = i + 1;
for (int v = A[i]; L; ++v) {
int next_L = left_ends.at(
min((int)size(left_ends) - 1, (1 << (v - A[i])) - 1));
ans += (int64_t)(L - next_L) * v;
L = next_L;
}
}
cout << ans << "\n";
}
Full Credit: Call an interval relevant if it is not possible to extend it to the left or to the right without increasing its value.
Claim: The number of relevant intervals is O(NlogN).
Proof: See the end of the analysis.
We'll compute the same quantities as in subtask 3, but this time, we'll transition from v?1 to v in time proportional to the number of relevant intervals with value v?1 plus the number of relevant intervals with value v, this will give us a solution in O(NlogN).
For a fixed value of v, say that an interval [l,r) is a segment if it contains no value greater than v, and min(Al?1,Ar)>v. Say that an interval is maximal with respect to v if it has value at most v and extending it to the left or right would cause its value to exceed v. Note that a maximal interval [l,r) must be relevant, and it must either have value equal to v or be a segment.
My code follows. ivals[i] stores all maximal intervals contained within the segment with left endpoint i. The following steps are used to transition from v?1 to v:
Apply halve on all segments containing more than one maximal interval (the left endpoints of every such segment are stored by active). Before, all intervals within the segment were maximal with respect to v?1. After, all intervals within the segment are maximal with respect to v.
Add a segment and a maximal interval of the form [i,i+1) for each i satisfying Ai=v, and then merge adjacent segments.
#include <bits/stdc++.h>
using namespace std;
template <class T> using V = vector<T>;
#define all(x) begin(x), end(x)
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
cin >> N;
V<int> A(N);
V<V<int>> with_A;
for (int i = 0; i < N; ++i) {
cin >> A[i];
while ((int)size(with_A) <= A[i]) with_A.emplace_back();
with_A[A[i]].push_back(i);
}
// sum(l ... r)
auto sum_arith = [&](int64_t l, int64_t r) {
return (r + l) * (r - l + 1) / 2;
};
// total number of intervals covered by list of maximal intervals
auto contrib = [&](const list<pair<int, int>> &L) {
int64_t ret = 0;
for (auto it = begin(L);; ++it) {
auto [x, y] = *it;
if (next(it) == end(L)) {
ret += sum_arith(0, y - x);
break;
} else {
int next_x = next(it)->first;
ret += int64_t(next_x - x) * y - sum_arith(x, next_x - 1);
}
}
return ret;
};
int64_t num_at_least = (int64_t)N * (N + 1) / 2;
auto halve = [&](list<pair<int, int>> &L) {
if (size(L) <= 1) return;
num_at_least += contrib(L);
int max_so_far = -1;
list<pair<int, int>> n_L;
auto it = begin(L);
for (auto [x, y] : L) {
while (next(it) != end(L) && next(it)->first <= y) ++it;
if (it->second > max_so_far) {
n_L.push_back({x, max_so_far = it->second});
}
}
swap(L, n_L);
num_at_least -= contrib(L);
};
// doubly linked list to maintain segments
V<int> pre(N + 1);
iota(all(pre), 0);
V<int> nex = pre;
int64_t ans = 0;
V<int> active; // active segments
// maximal intervals within each segment
V<list<pair<int, int>>> ivals(N + 1);
for (int v = 1; num_at_least; ++v) {
ans += num_at_least; // # intervals with value >= v
V<int> n_active;
for (int l : active) {
halve(ivals[l]);
if (size(ivals[l]) > 1) n_active.push_back(l);
}
if (v < (int)size(with_A)) {
for (int i : with_A[v]) {
int l = pre[i], r = nex[i + 1];
bool should_add = size(ivals[l]) <= 1;
pre[i] = nex[i + 1] = -1;
nex[l] = r, pre[r] = l;
ivals[l].push_back({i, i + 1});
--num_at_least;
ivals[l].splice(end(ivals[l]), ivals[i + 1]);
should_add &= size(ivals[l]) > 1;
if (should_add) n_active.push_back(l);
}
}
swap(active, n_active);
}
cout << ans << "\n";
}
Proof of Claim: Let f(N) denote the maximum possible number of relevant subarrays for a sequence of size N. We can show that f(N)≤O(logN!)≤O(NlogN). This upper bound can be attained when all elements of the input sequence are equal.
The idea is to consider a Cartesian tree of a. Specifically, suppose that one of the maximum elements of a is located at position p (1≤p≤N). Then
f(N)≤f(p?1)+f(N?p)+#(relevant intervals containing p).
WLOG we may assume 2p≤N.
Lemma:
#(relevant intervals containing p)≤O(plog(Np))
Proof of Lemma: We can in fact show that
#(relevant intervals containing p with value ap+k)≤min(p,2k):0≤k≤?log2N?.
The p comes from all relevant intervals with a fixed value having distinct left endpoints and the 2k comes from the fact that to generate a relevant interval of value ap+k+1 containing p, you must start with a relevant interval of value ap+k and choose to extend it either to the right or to the left.
To finish, observe that the summation ∑?log2N?k=0#(relevant intervals containing p with value ap+k) is dominated by the terms satisfying log2p≤k≤?log2N?. ■
Since O(plogNp)≤O(log(Np))≤O(logN!(p?1)!(N?p)!)
f(N)≤f(p?1)+f(N?p)+#(relevant intervals containing p)≤O(log(p?1)!)+O(log(N?p)!)+O(logN!?log(p?1)!?log(N?p)!)≤O(logN!).
Here is an alternative approach by Danny Mittal that uses both the idea from the subtask 4 solution and the Cartesian tree. He repeatedly finds the index of the rightmost maximum amida1…mid?1amid+1…NamidO(NlogN)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Revisited262144Array {
static int n;
static int[] xs;
static int[] left;
static int[] right;
static int[] forward;
static int[] reverse;
static long answer = 0;
public static int reduceForward(int start, int length, int lgFactor) {
if (lgFactor == 0) {
return length;
}
int factor = 1 << Math.min(lgFactor, 20);
int j = start;
for (int k = start + factor - 1; k < start + length - 1; k += factor) {
forward[j++] = forward[k];
}
forward[j++] = forward[start + length - 1];
return j - start;
}
public static void reduceReverse(int start, int length, int lgFactor) {
if (lgFactor == 0) {
return;
}
int factor = 1 << Math.min(lgFactor, 20);
if (length > factor) {
int j = start + 1;
for (int k = start + 1 + ((length - factor - 1) % factor); k < start + length; k += factor) {
reverse[j++] = reverse[k];
}
}
}
public static int funStuff(int from, int mid, int to, int riseTo) {
if (from > to) {
return 0;
}
int leftLength = funStuff(from, left[mid], mid - 1, xs[mid]);
int rightLength = funStuff(mid + 1, right[mid], to, xs[mid]);
int leftStart = from;
int rightStart = mid + 1;
int last = mid - 1;
for (int j = 1; j <= rightLength + 1; j++) {
int frontier = j > 1 ? forward[rightStart + (j - 2)] : mid;
long weight = frontier - last;
last = frontier;
int lastInside = mid + 1;
int leftLast = leftLength == 0 ? mid : reverse[leftStart];
for (int d = 0; d <= 18 && lastInside > leftLast; d++) {
if (1 << d >= j) {
int frontierInside;
if (1 << d == j) {
frontierInside = mid;
} else if (1 << d <= j + leftLength) {
frontierInside = reverse[leftStart + leftLength + j - (1 << d)];
} else {
frontierInside = leftLast;
}
long weightInside = lastInside - frontierInside;
lastInside = frontierInside;
answer += weight * weightInside * ((long) (xs[mid] + d));
}
}
}
forward[leftStart + leftLength] = mid;
System.arraycopy(forward, rightStart, forward, leftStart + leftLength + 1, rightLength);
reverse[leftStart + leftLength] = mid;
System.arraycopy(reverse, rightStart, reverse, leftStart + leftLength + 1, rightLength);
int length = reduceForward(leftStart, leftLength + 1 + rightLength, riseTo - xs[mid]);
reduceReverse(leftStart, leftLength + 1 + rightLength, riseTo - xs[mid]);
return length;
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(in.readLine());
StringTokenizer tokenizer = new StringTokenizer(in.readLine());
xs = new int[n];
for (int j = 0; j < n; j++) {
xs[j] = Integer.parseInt(tokenizer.nextToken());
}
left = new int[n];
right = new int[n];
ArrayDeque<Integer> stack = new ArrayDeque<>();
for (int j = 0; j < n; j++) {
while (!stack.isEmpty() && xs[stack.peek()] <= xs[j]) {
left[j] = stack.pop();
}
if (!stack.isEmpty()) {
right[stack.peek()] = j;
}
stack.push(j);
}
while (stack.size() > 1) {
stack.pop();
}
forward = new int[n];
reverse = new int[n];
funStuff(0, stack.pop(), n - 1, Integer.MAX_VALUE);
System.out.println(answer);
}
}

USACO2022美国公开赛白金组问题一——262144

Bessie likes downloading games to play on her cell phone, even though she does find the small touch screen rather cumbersome to use with her large hooves.
She is particularly intrigued by the current game she is playing. The game starts with a sequence of N positive integers a1,a2,…,aN (2≤N≤262,144), each in the range 1…106. In one move, Bessie can take two adjacent numbers and replace them with a single number equal to one greater than the maximum of the two (e.g., she might replace an adjacent pair (5,7) with an 8). The game ends after N?1 moves, at which point only a single number remains. The goal is to minimize this final number.
Bessie knows that this game is too easy for you. So your job is not just to play the game optimally on a, but for every contiguous subsequence of a.
Output the sum of the minimum possible final numbers over all N(N+1)2 contiguous subsequences of a.
INPUT FORMAT (input arrives from the terminal / stdin):
First line contains N.
The next line contains N space-separated integers denoting the input sequence.
OUTPUT FORMAT (print output to the terminal / stdout):
A single line containing the sum.
SAMPLE INPUT:
6
1 3 1 2 1 10
SAMPLE OUTPUT:
115
There are 6?72=21 contiguous subsequences in total. For example, the minimum possible final number for the contiguous subsequence [1,3,1,2,1] is 5, which can be obtained via the following sequence of operations:
original -> [1,3,1,2,1]
combine 1&3 -> [4,1,2,1]
combine 2&1 -> [4,1,3]
combine 1&3 -> [4,4]
combine 4&4 -> [5]
Here are the minimum possible final numbers for each contiguous subsequence:
final(1:1) = 1
final(1:2) = 4
final(1:3) = 5
final(1:4) = 5
final(1:5) = 5
final(1:6) = 11
final(2:2) = 3
final(2:3) = 4
final(2:4) = 4
final(2:5) = 5
final(2:6) = 11
final(3:3) = 1
final(3:4) = 3
final(3:5) = 4
final(3:6) = 11
final(4:4) = 2
final(4:5) = 3
final(4:6) = 11
final(5:5) = 1
final(5:6) = 11
final(6:6) = 10
SCORING:
Test cases 2-3 satisfy N≤300.
Test cases 4-5 satisfy N≤3000.
In test cases 6-8, all values are at most 40.
In test cases 9-11, the input sequence is non-decreasing.
Test cases 12-23 satisfy no additional constraints.
Problem credits: Benjamin Qi

2011 年 11 月竞赛——最终结果

USACO 2011 年 11 月学术活动以算法编程问题为特色,涵盖了广泛的技术和难度级别。 单击此处 查看比赛问题和解决方案。

共有1450名参赛者参加了比赛——创下了新的记录!我们看到来自 74 个不同国家的参与者:

566 USA 99 CHN 66 VNM 42 IRN 40 BLR 39 IDN 38 GEO 37 CAN 34 ROM33 KAZ 31 MEX 28 TUR 23 RUS 22 BRA 21 ITA 20 TWN 16 KOR 16 HRV14 ROU 14 LTU 14 DEU 14 BGR 13 MKD 13 GRC 13 EGY 12 IND 11 YUG11 COL 11 AUS 10 TKM 9 POL 8 FRA 7 UKR 6 VEN 6 ARM 5 TJK5 SRB 5 SGP 5 LVA 5 LKA 5 CUB 5 BGD 4 SVN 4 PER 3 THA3 NZL 3 GBR 3 EST 3 DOM 2 ZAF 2 SYR 2 PRT 2 MNG 2 LUX2 INA 2 HKG 2 DNK 2 AUT 2 ARG 1 TUV 1 SVK 1 NED 1 MDA1 MAR 1 LBN 1 JPN 1 JAM 1 ISL 1 IRL 1 GER 1 FIN 1 CZE1 CYP 1 ARE

参与者平均提交 2.6 个问题的解决方案。总共有 3878 份评分提交,按语言细分如下(这是我们第一次支持 Python 作为学术活动语言):

2264 C++

1041 Java

330 Pascal

173 C

70 Python

黄金组成绩

黄金组共有167人参加,其中98人为预科生。

共有13名预科生获得满分;祝贺您取得如此卓越的成就!大学预科金牌得主是:

Country Grad Name Country Grad Name
VNM   2012 Huy Tran SYR   2013 Kinan Sarmini
ROM   2013 Gavrila Vlad BLR   2012 Gennady Korotkevich
CHN   2012 Martin Token BGR   2012 Rumen Hristov
BLR   2012 Adam Bardashevich CHN   2016 Yuetong Wang
CHN   2013 LiJie Chen CHN   2012 Wenhan Huang
USA   2013 Johnny Ho IRN   2013 SeyedHamed Valizadeh
CHN   2014 Nanxin Chen

也恭喜黄金组满分的17位观察员:

Country Name Country Name Country Name
LVA Eduard Kalinicenko EGY Hamza Ibrahim CHN Zechao Shang
KAZ Ali-Amir Aldan BLR Aleksey Ropan VNM NguyenTS Nguyen
CHN Qu Peng IRN Saeed Ilchi ROM Paul-Dan Baltescu
DEU Daniel Kirch ZAF Bruce Merry CHN Neal Zane
DEU Thomas Fersch UKR Yaroslav Tverdokhlib CAN Tyson Andre
DEU Alexander Rass CHN Kuan Yang

白银组成绩

白银组共有200名参赛者,其中166名是预科生。

该部门的三个问题需要巧妙的算法思维,对大多数参赛者来说都具有挑战性。虽然高分不少,但只有三位参赛者(三位都是预科生)交出了满分:

Country Grad Name
USA   2014 Steven Hao
USA   2013 Calvin Deng
CHN   2013 Grace Tsai

恭喜您在这场艰巨的比赛中取得满分!你们三个都被提升到黄金组以备将来参加比赛。如果任何参与者在三个问题中的两个问题上获得满分,也可以升级为金牌——如果您属于此类并希望参加 12 月的金牌学术活动,请发送电子邮件至 bcdean@clemson.edu。

青铜组成绩

铜牌组共有1083人参赛,其中预科生829人。

恭喜获得满分的79名预科生和38名观察员!为了以后的比赛,你们都被提升到了白银组。大学预科铜牌获得者是:

Country Grad Name Country Grad Name
RUS   2013 Alexander Mokin CHN   2014 Chen Jianing
RUS   2013 Danil Medvedev USA   2013 Davis Wang
VNM   2013 Dat Duong LTU   2013 Vladimir Daglis
LTU   2013 Edgaras Liberis USA   2013 Albert Chu
GEO   2016 George Skhirtladze ROU   2016 Paul Gramatovici
USA   2013 Derek Lou ROM   2014 Olariu Ciprian
FRA   2012 Simon Mauras USA   2013 Sunny Nahar
CHN   2013 Xiang Wu DEU   2012 Julian Labeit
TWN   2013 Jhih Bang Hsieh TWN   2012 Shao-Chuan Lee
USA   2013 Jeffrey Yan KAZ   2013 Eldar Aimakov
USA   2012 Scott DellaTorre VNM   2013 ThnhAn Hng
USA   2013 Cody Silverman MEX   2014 Daniel Talamas
USA   2013 Yimo Chen VNM   2012 Bao Chiem Duy
MEX   2013 Edgar Augusto Santiago Nieves AUS   2014 Ray Li
VNM   2013 Linh Ta USA   2014 Jakob Weisblat
VNM   2012 Thanh Nguyen BRA   2013 Kahn Slap
BRA   2014 Igor Wolff Resplande CHN   2013 Peter Lee
LKA   2012 Hirantha Subasinghe RUS   2013 Kirill Borozdin
ROM   2012 Cristian Lambru RUS   2013 Vladimir Polushin
VNM   2013 Tuán Anh Nguyen RUS   2012 Oleg Ivanov
USA   2013 Bo Moon MKD   2015 Vasil Kuzevski
CAN   2014 Stella Lau UKR   2012 Valentin Lukyanets
IRN   2013 Sobhan Miryoosefi PER   2012 Dennis Huillca
RUS   2012 Gerald Agapov USA   2013 Allan Sadun
VNM   2012 Shin Doyle MEX   2013 Freddy Roman
USA   2014 Abhay Goel IDN   2013 Jonathan Irvin Gunawan
HRV   2014 Martin Gluhak ISL   2012 Bjarki Agust Gudmundsson
RUS   2012 Egor Suvorov RUS   2012 Petr Mayorov
CAN   2013 Mehwar Raza TUR   2012 Mustafa Erdogan
VNM   2013 Life Keeper KAZ   2012 Ilya Dronov
KAZ   2012 Dias Abdraimov SRB   2014 Ivan Stosic
IRN   2013 Daniyal Mehrjerdi INA   2012 Setiadi Alvin
ITA   2013 Davide Pallotti ITA   2013 Andrea Battistello
IDN   2013 Pusaka Kaleb Setyabudi ITA   2013 Matteo Almanza
AUT   2012 Markus Hasenohrl TUR   2012 Safa Andac
IDN   2013 M Aji Muharrom CAN   2014 Henry Wu
VNM   2013 Bao Nguyen Le USA   2015 Andrew He
IDN   2013 Vincent The INA   2012 Amanda Pratama
IDN   2012 Jennifer Santoso ITA   2012 Gabriele Farina
ITA   2013 Daniele Del Giudice

获得满分的铜牌观察员是:

Country Name Country Name Country Name
IRN Hooman Hashemi MDA Luncasu Victor CAN Robert Xiao
CHN Baoer Yu VNM QViet Ky VNM Hoang Le
CHN Shijian Liu IRN Shahriar Heshmat CUB Ernesto Carvajal
CHN Yuwen Li IDN David Christopher AUS Andrew Haigh
KOR GyeongGeun Kim ARG Federico Pousa USA Cheng Pan
DNK Gert Hansen CAN Alex Velazquez CHN Guodong Feng
CHN Lei Huang ROM Andrei - GBR Sean Quah
CHN Derrick Chou FRA Zamato Lassts PER Johann Cortez
RUS Mikhail Mayorov GBR Robin Lee CHN Tianyu Lou
COL Alejandro Alejandro ROM Laurentiu Cristian Ion SGP Mark Theng
DEU Florin-Cristian Ghesu CHN Han Zhu BRA Leonardo Conegundes
KOR Myungwoo Chun CHN W Jn TWN How Jing

最后的评论

我对每个部门的整体结果都很满意——分数的分布表明问题确实很有挑战性,但希望不会难到令人沮丧的地步。如果您是 USACO 的新手,您现在可以很好地了解我们比赛的难度。

本次比赛是第一次在我们全新的网络基础设施上运行;我们将继续添加功能和改进,因此下一次比赛应该具有您在过去的 USACO 比赛中习惯的所有功能,包括比赛期间关于您的程序是否正确回答示例输入的实时反馈,查看以前的能力提交、比赛结束后的分析模式、使用您自己的输入在评分服务器上运行您的程序以达到计时目的的能力,等等??。我感谢在迁移过程中与我们一起努力的每一个人,我也感谢你们给我的所有反馈,以帮助我改进下一次比赛的系统。

我很高兴在这次比赛中作弊似乎最少,我希望它能保持这种状态。不幸的是,我确实不得不删除一些在比赛中作弊的参与者(主要是在比赛期间使用多个帐户——不要这样做!)。作弊永远不会真正对你有利,这将导致你被禁止参加未来所有的 USACO 比赛。另外,请在您的帐户中使用您的真实姓名;尽管我尊重“Gangster Veggies”和“Fuzzy Fuzzy”等参与者精致的幽默感,但我通常会从最终结果中删除条目,直到它们来自具有合法名称的帐户。

感谢许多人的帮助,让这场比赛得以顺利开展。USACO 教练组——Neal Wu、Nathan Pinsker、Mark Gordon、Richard Peng、Albert Gu、Jacob Steinhardt 和 Ben Cousins 在帮助解决方案和测试数据方面发挥了重要作用。感谢 Rob Kolstad 帮助网站过渡,感谢 Chad Waters 在新后端评分系统方面的帮助。Ray Li 和 Rob Seay 贡献了优秀的问题(如果您对问题有好的想法,请按我的方式发送——我们一直在寻找高质量的问题!)。感谢 Clemson CCIT 的人员,他们为我们提供了新服务器。最后,非常感谢我们的赞助商,他们的支持绝对至关重要且非常感谢:IBM、Usenix、TwoSigma 和 Jump Trading。

 

2011 年 12 月竞赛——最终结果

USACO 2011 年 12 月学术活动以算法编程问题为特色,涵盖了广泛的技术和难度级别。 单击此处 查看比赛问题和解决方案。

共有来自 68 个不同国家的 1102 名参赛者参赛:

438 USA 79 VNM 76 CHN 40 IRN 34 ROU 31 GEO 27 RUS27 KAZ 26 BLR 22 MEX 16 LTU 16 AUS 15 ARM 14 IDN14 CAN 13 BGR 11 UKR 11 TWN 11 KOR 10 ITA 10 DEU9 YUG 8 TUR 8 SRB 8 HRV 7 TJK 7 MKD 7 FRA7 EGY 7 BRA 6 TKM 6 GRC 6 COL 6 BGD 5 VEN5 POL 5 LVA 5 CUB 4 PER 3 SYR 3 LKA 3 IND3 DOM 3 CZE 2 ZAF 2 THA 2 SWE 2 SVK 2 PRT2 AUT 2 ARG 1 SVN 1 SGP 1 NZL 1 MNG 1 MDA1 LUX 1 JPN 1 ISL 1 GER 1 GBR 1 FIN 1 ESP1 DNK 1 BEN 1 ARE

参与者平均提交 2.1 个问题的解决方案。总共有 2351 份评分提交,按语言细分如下:

1375 C++

592 Java

294 Pascal

55 C

35 Python

黄金组成绩

黄金组共有130名参赛者,其中80名是预科生。

事实证明,本次比赛中的金牌问题非常具有挑战性,时间和记忆力的限制给许多参与者带来了困难。本次黄金组唯一满分的是来自克罗地亚的观察员Lovro Puzar。祝贺洛夫罗取得这一非凡成就!大学预科的参与者中没有满分,但许多人仍然取得了令人印象深刻的成绩。黄金组前十名的大学预科参赛者是:

Country Grad Name Score
VNM   2012 Huy Tran 897
USA   2012 Mitchell Lee 846
TWN   2015 Peter Yu 833
CHN   2015 Yuetong Wang 831
CHN   2012 Wenhan Huang 806
BLR   2012 Gennady Korotkevich 769
CHN   2012 Martin Token 752
SYR   2013 Kinan Sarmini 722
USA   2013 Johnny Ho 701
CHN   2014 Silly Cross 638

前十名观察员是:

Country Name Score
HRV Lovro Puzar 1000
POL Adam Karczmarz 974
UKR Yaroslav Tverdokhlib 923
BGD Nazmul Hasan 897
CZE Filip Hlasek 897
CAN Jacob Plachta 703
KAZ Ali-Amir Aldan 703
VNM VuongLinh Nguyen 679
DEU Alexander Rass 667
DEU Fabian Gundlach 667

白银组成绩

银牌组共有 217 名参赛者,其中 175 名是预科生。

本次比赛中的三个银牌问题需要标准算法技术和“开箱即用”思维的结合。五名预科生获得满分被祝贺:

Country Grad Name
USA   2013 Yimo Chen
IRN   2013 Daniyal Mehrjerdi
CHN   2013 Lei Xu
POL   2012 Bartek Dudek
RUS   2012 Egor Suvorov

连同 3 名观察员:

Country Name
UKR Ivan Mistreanu
RUS Mikhail Mayorov
MKD Igor Kulev

恭喜您在这场艰巨的比赛中取得满分!为了以后的比赛,你们都被提升到黄金组。如果任何参与者获得 850 分或更高的分数,也可以升级为黄金——如果您属于这一类别并希望参加 1 月份的黄金学术活动,请发送电子邮件至 bcdean@clemson.edu。(想知道晋级标准是如何设置的朋友请注意:每场比赛都是不同的,所以我们在审查问题和结果后仔细选择每场比赛的晋级标准,以确保被晋升的人已经做好充分准备下一个部门的挑战)。

青铜组成绩

铜牌组共有755人参赛,其中预科生597人。

恭喜获得满分的14名预科生和4名观察员!大学预科铜牌获得者是:

Country Grad Name
USA   2014 Brian Shimanuki
VNM   2013 Tung Tran
GEO   2013 Tornike Mandzzulashvili
GEO   2014 Nika Nadiradze
ROU   2017 Pavel Ori
CHN   2013 Pu Chen
TWN   2015 Wei Chen Liao
AUS   2015 Michael Chen
USA   2013 Wenkai Lei
KOR   2014 Yechan Bae
VNM   2014 Linh To Ngoc
CHN   2016 Zhouxing Shi
USA   2014 Douglas Chen
RUS   2012 Alex Gordeev

获得满分的铜牌观察员是:

Country Name
CHN Shimi Zhang
USA Nick Buelich
VNM Phong Duong Thanh
DNK Anders Roy Christiansen

所有获得满分的参赛者将自动晋升为银牌组以参加未来的比赛。900分以上者,可酌情晋升;如果是这样,请联系 bcdean@clemson.edu。

最后的评论

这场比赛似乎比之前的比赛更具挑战性,尤其是在黄金级别。不过,我对三个部门的整体分布还是很满意的。

我们的比赛基础设施不断改进,比赛中只出现了一些小的技术问题。我们遇到的主要技术问题是我们的评分机和主服务器之间偶尔出现数据库连接错误,这主要导致一些参与者长时间等待反馈;这应该在下一次比赛中解决,但为了确保一切设置正确,我们需要暂时让评分机离线,这意味着“分析模式”(您可以在其中重新提交您的解决方案到旧比赛)将不可用。在一月份的比赛之后寻找这个功能。

我在设置和运行本次比赛时得到了很多出色的帮助。非常感谢 Nathan Pinsker 和 Albert Gu 帮助组织金牌比赛,感谢 Alex Chen 帮助组织银牌比赛,感谢 Kalki Seksaria 帮助组织铜牌比赛。贡献时间和专业知识的其他教练组成员包括 Neal Wu、Mark Gordon、Richard Peng、Ben Cousins、Travis Hance、Chris Corsi 和 Chad Waters。一如既往,如果你也想通过向我发送高质量的问题来为 USACO 学术活动做出贡献,请不要犹豫!还要感谢我们的翻译人员,他们帮助我们极大地扩大了比赛的范围,最后还要感谢我们的赞助商,他们的支持绝对至关重要,非常感谢:IBM、Usenix、TwoSigma 和 Jump Trading。

 

2012 年 1 月竞赛——最终结果

USACO 2012 年 1 月学术活动以算法编程问题为特色,涵盖了广泛的技术和难度级别。 单击此处 查看比赛问题和解决方案。

共有来自 63 个不同国家的 846 名参赛者参加了比赛:

346 USA 58 CHN 40 IRN 38 VNM 24 BLR 21 RUS 20 KAZ 17 ROU16 UKR 16 GEO 16 CAN 15 MEX 15 ITA 13 TUR 13 IDN 10 TWN10 DEU 9 GRC 9 BGD 8 YUG 8 TKM 8 SRB 8 HKG 7 BGR6 LVA 5 KOR 5 HRV 5 AZE 5 ARM 4 VEN 4 TJK 4 POL4 MKD 4 IND 4 FRA 4 EGY 4 CUB 4 COL 4 AUS 3 ZAF3 LTU 3 DOM 2 SGP 2 PER 2 GBR 2 DNK 2 CZE 1 SYR1 SWE 1 SVK 1 PRT 1 PHL 1 NZL 1 MOZ 1 LUX 1 JPN1 ISL 1 IRL 1 EST 1 ESP 1 BRA 1 BEN 1 AUT

参与者平均提交 2.5 个问题的解决方案。总共有 2078 份评分提交,按语言细分如下:

1227 C++

542 Java

215 Pascal

50 C

44 Python

黄金组成绩

黄金组共有122名参赛者,其中74名是预科生。

这一轮的黄金问题相当棘手。在大学预科类别中,Scott Wu、Gennady Korotkevich 和 Johnny Ho 并列第一,在观察员类别中,Adam Karczmarz、Thomas Fersch 和 Yaroslav Tverdokhlib 获得了 3 个满分. 祝贺这些杰出的问题解决者,以及所有其他在如此艰难的比赛中获得高分的人!我特别自豪地看到 3 个美国选手进入前 4 名!

黄金组前十名的大学预科参赛者是:

Country Grad Name Score
USA   2015 Scott Wu 967
BLR   2012 Gennady Korotkevich 967
USA   2013 Johnny Ho 967
USA   2012 Alex Chen 933
BLR   2013 Sergey Kulik 833
CHN   2015 Yuetong Wang 800
CHN   2013 Wang Ruosong 800
RUS   2012 Ivan Lakhtanov 800
IRN   2013 SeyedHamed Valizadeh 767
CHN   2012 Martin Token 767

前十名观察员是:

Country Name Score
POL Adam Karczmarz 1000
DEU Thomas Fersch 1000
UKR Yaroslav Tverdokhlib 1000
CHN Bai Ge 967
VNM VuongLinh Nguyen 933
HRV Lovro Puzar 933
BGD Nazmul Hasan 900
CAN Jacob Plachta 900
UKR Ivan Zdomsky 833
BLR Eugene Gritskevich 800

白银组成绩

银牌组共有189名参赛者,其中156名是预科生。

与黄金问题一样,白银问题也非常具有挑战性。四名大学预科生(Simon Mauras、Yuguan Chen、Yunhao Huang 和 Shenghan Gao)和四名观察员(AndersRoy Christiansen、Gert Hansen、PakHay Chan 和 Andrew Haigh)获得了满分。祝贺大家!大学预科组前十名成绩分别是:

Country Grad Name Score
FRA   2012 Simon Mauras 1000
CHN   2014 Yuguan Chen 1000
CHN   2015 Yunhao Huang 1000
CHN   2013 Shenghan Gao 1000
IRN   2013 Hooman Hashemi 976
VNM   2013 Dat Duong 929
CHN   2015 Huang Taoan 905
USA   2014 Stanley Cen 905
USA   2014 Jerry Ma 881
CHN   2013 Pu Chen 881

前十名观察员是:

Country Name Score
DNK AndersRoy Christiansen 1000
DNK Gert Hansen 1000
HKG PakHay Chan 1000
AUS Andrew Haigh 1000
VNM Minh-Hoang Le 900
CHN Tianyu Lou 800
RUS Maksim Banin 667
CHN Song Anliang 667
ZAF Ashraf Moolla 657
USA Cheng Pan 567

所有在至少两个问题上获得满分的参赛者将自动晋级为下一届比赛的黄金组。

青铜组成绩

铜牌组共有552人参赛,其中预科生436人。

恭喜获得满分的40名预科生和14名观察员!大学预科铜牌获得者是:

Country Grad Name
KAZ   2013 Rustam Azimov
SRB   2013 Nikola Klipa
VNM   2013 Phuoc Dat Nguyen
RUS   2013 Dmitry Gorbunov
VNM   2013 Nhat Tran
ROU   2014 Mihai Gheorghe
LTU   2013 Marius Latinis
KOR   2016 Jeong JongKwang
USA   2012 Brian Wai
RUS   2012 Nikolay Mischenko
DEU   2012 Maximilian J
RUS   2013 Vladislav Tyulbashev
USA   2013 Thomas Schultz
AUS   2012 Darren Shen
TWN   2013 Andrew Lai
RUS   2012 Vlad Chabanenko
TJK   2015 Abdukodir Kurbonzoda
GRC   2013 Konstantinos Kanellis
VNM   2013 Le Viet Thanh Long
TUR   2013 Alperen Yakut
GRC   2013 George Karagkiaouris
DEU   2014 Markus Schmidt
CZE   2014 Ondrej Hubsch
HKG   2012 Dipy O
MKD   2014 Mladen Dimovski
VNM   2013 Trung Dinh
ITA   2012 Marco Natuzzi
SRB   2012 Predrag Ilkic
VNM   2012 Jack Akita
KAZ   2015 Daniyar Maminov
IRN   2013 Hossein Hosseinvand
HKG   2013 Chun Yin Sampson Lee
VNM   2012 VietAnh Do
SRB   2013 Slobodan Ilkic
ITA   2012 Lorenzo Gatto
CHN   2013 Zhizhi Chen
BLR   2012 Vladislav Trukhanovich
MEX   2012 Eric Valdivia
HKG   2015 Yik WaiPan
BLR   2012 Konstantin Vilchevski

获得满分的铜牌观察员是:

Country Name
DEU Stefan Koegel
USA Adrian Nazco
VNM ThanhCanh NguyenHuu
BRA Fernando Fonseca
VNM Gia Huy
YUG Filip Katanic
BGD Nahiyan Kamal
VNM Quang PeLe
DOM Carlos Toribio
MEX Rodrigo BurgosDominguez
VNM Hung Nguyen
YUG Isidora Sekulic
JPN Dijkstra Takuma
CHN Jianjin Fan

所有分数严格高于 900 分的参赛者将自动晋升为银牌组,以参加未来的比赛。

最后的评论

虽然本次比赛在各个层面都颇具挑战性,但总的分数分布还是比较合理的。这一次技术问题最少——我们新的比赛平台终于达到了稳定点,我们应该能够很快用新的和令人兴奋的功能来扩展它。

感谢许多对本次比赛提供极大帮助的个人。特别感谢 Mark Gordon 协调金牌学术活动,感谢 Neal Wu、Mark Gordon、Videh Seksaria、Fatih Gelgi 和 Kalki Seksaria 贡献的问题,以及 Mark Gordon、Neal Wu、Richard Peng、Jonathan Paulson、Ray Li、Bruce Merry和 Alex Chen 提供解决方案。一如既往,如果你也想通过向我发送高质量的问题来为 USACO 学术活动做出贡献,请不要犹豫!还要感谢 Chad Waters 和 Clemson CCIT 员工在我们的比赛基础设施方面的帮助,感谢我们的翻译人员,他们帮助我们大大扩大了比赛的范围,最后感谢我们的赞助商,他们的支持绝对至关重要,非常感谢:IBM、Usenix 、TwoSigma 和Jump Trading。