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;
3
4using ll = long long;
5
6using vi = vector<int>;
7#define pb push_back
8#define rsz resize
9#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!

Give Us Feedback on Baltic OI 2015 - Hacker!