Baltic OI 2015 - Hacker
Author: Michael Cao
Intuition
In this problem, we're asked to play a game where players take turns claiming unclaimed elements in a circular array that are adjacent to one of their previously claimed elements (or any unclaimed element on their first turns). Both players try to maximize the sum of values of their chosen elements.
After playing around with the game, we can make some important observations.
Observation 1
Observation
At the end of the game, the first player will control a subarray (a contiguous subsequence) of the circular array of length exactly , and the second player will control the remaining elements.
Since each player can only choose an element not adjacent to any other element once (the first move), the elements each player claims must form a subarray. Also, notice that any move made by either player will increase the length of the subarray they control by one, and both players will always have a valid move. Therefore, because the first player moves first, the subarray they control will be of length .
Observation 2
Observation
For some first move made by the first player claiming index , the second player can always force the first player to control any subarray of length containing .
Consider the following strategy: for some move by the first player extending to the left or right, make the opposite move.
Using this strategy, the second player can force the first player to control any subarray of length containing the first players first move depending on the second players first move.
Computing the Solution
Using these observations, the answer equals:
where represents a set of sums for all subarrays of length containing in the circular array, .
Transforming the Circular Array
First, to deal with the circular aspect of the array, let's concatenate it onto itself to create an array of length and call it . Now, we only need to compute subarrays on a linear array, where where represents the set of subarrays containing in .
Using An Ordered Set
If we iterate over in , then we can store the running ordered set and use it to update . For , add the sum over the subarray to (you can compute this using prefix sums). Additionally, if , remove the sum over . Then, we can compute the minimum value of for some by querying for the smallest value in the ordered set.
Warning!
Make sure to use a std::multiset
because there can be duplicate sums.
Code
1#include <bits/stdc++.h>2using namespace std;34using ll = long long;56using vi = vector<int>;7#define pb push_back8#define rsz resize9#define all(x) begin(x), end(x)10#define sz(x) (int)(x).size()
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!