Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

USACO问题集

Download as pdf or txt
Download as pdf or txt
You are on page 1of 134

USACO

Elite 2008 January Compe on USACO Contest Analysis and Data..............................................................3


BRONZE PROBLEMS...................................................................................................................................3
Costume Party [Neal Wu, 2007].............................................................................................................3
Elec on Time [Jeffrey Wang, 2007].......................................................................................................5
iCow [Jeffrey Wang, 2008].....................................................................................................................7
SILVER PROBLEMS......................................................................................................................................9
Cow Contest [Neal Wu, 2007]................................................................................................................9
Running [Neal Wu, 2007].....................................................................................................................11
Telephone Lines [Paul Chris ano, 2007]..............................................................................................13
GOLD PROBLEMS.....................................................................................................................................16
Haybale Guessing [Brian Dean, 2003]..................................................................................................16
Ar ficial Lake [Ma McCutchen, 2006]...............................................................................................19
Cell Phone Network [Jeffrey Wang, 2007]...........................................................................................23
Special 2007 Chinese Compe on contest.................................................................................................26
GOLD PROBLEMS.....................................................................................................................................26
Summing Sums [Neal Wu, 2007].........................................................................................................26
The Bovine Accordion and Banjo Orchestra [Lei Huang, 2007]...........................................................31
Treasure [Yang Yi, 2007].......................................................................................................................35
Elite 2007 December Compe on contest..................................................................................................41
BRONZE PROBLEMS.................................................................................................................................41
Bookshelf [Neal Wu, 2007]..................................................................................................................42
Bookshelf 2 [Neal Wu, 2007]...............................................................................................................44
Card Stacking [Jeffrey Wang, 2007].....................................................................................................46
SILVER PROBLEMS....................................................................................................................................49
Charm Bracelet [Kolstad/Cox, 2006]....................................................................................................49
Building Roads [Richard Ho, 2007]......................................................................................................53
Mud Puddles [Jeffrey Wang, 2007]......................................................................................................56
GOLD PROBLEMS.....................................................................................................................................61
Sightseeing Cows [Reid Barton, 2007].................................................................................................61
Gourmet Grazers [Alex Schwendner, 2007].........................................................................................65
Best Cow Line, Gold [Christos Tzamos, 2007]......................................................................................68
Elite 2007 November Compe on contest.................................................................................................71
BRONZE PROBLEMS.................................................................................................................................71
Explora on [Jeffrey Wang, 2007].........................................................................................................71
Speed Reading [Jeffrey Wang, 2007]...................................................................................................74
Avoid The Lakes [Jeffrey Wang, 2007].................................................................................................76
SILVER PROBLEMS....................................................................................................................................78
Cow Hurdles [Neal Wu, 2007]..............................................................................................................78
Milking Time [Jeffrey Wang, 2007]......................................................................................................81
Best Cow Line [Christos Tzamos, 2007]................................................................................................84
GOLD PROBLEMS.....................................................................................................................................88
Telephone Wire [Jeffrey Wang, 2007]..................................................................................................88
Cow Relays [Erik Bernhardsson, 2003]................................................................................................90
Sunscreen [Russ Cox, 2001].................................................................................................................93
Elite 2008 January Competition USACO Contest Analysis
and Data

BRONZE PROBLEMS

*****************************************************************************

Costume Party [Neal Wu, 2007]

It's Halloween! Farmer John is taking the cows to a costume party, but
unfortunately he only has one costume. The costume fits precisely two cows
with a length of S (1 <= S <= 1,000,000). FJ has N cows (2 <= N <= 20,000)
conveniently numbered 1...N; cow i has length L i (1 <= Li <= 1,000,000). Two
cows can fit into the costume if the sum of their lengths is no greater than
the length of the costume. FJ wants to know how many pairs of two distinct
cows will fit into the costume.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and S

* Lines 2..N+1: Line i+1 contains a single integer: L i

SAMPLE INPUT (file costume.in):

4 6
3
5
2
1

OUTPUT FORMAT:

* Line 1: A single integer representing the number of pairs of cows FJ


can choose. Note that the order of the two cows does not
matter.
SAMPLE OUTPUT (file costume.out):

OUTPUT DETAILS:

The four pairs are as follows: cow 1 and cow 3; cow 1 and cow 4; cow 2 and
cow 4; and finally cow 3 and cow 4.

We first sort the heights, using an efficient sort, which takes O(N log N)
time. Then, for each height k in the list, we wish to (efficiently) find the
index of the largest height that, when added to k, produces a sum less than H.
After we find this index, we can count the number of heights that, when added
to k, satisfy the given property. The simplest way to find this is with a
binary search, which is implemented in the solution below:

#include <algorithm>
#include <cstdio>
using namespace std;

FILE *fout = fopen ("costume.out", "w");


FILE *fin = fopen ("costume.in", "r");

const int MAXN = 20005;

int N, H, total;
int height [MAXN];

// finds the index of the first position whose height is <= value
inline int binsearch (int value)
{
int lo = 0, hi = N - 1, mid;

while (lo < hi)


{
mid = (lo + hi + 1) >> 1;

if (height [mid] <= value)


lo = mid;
else
hi = mid - 1;
}

return lo;
}

int main ()
{
fscanf (fin, "%d %d", &N, &H);

for (int i = 0; i < N; i++)


fscanf (fin, "%d", height + i);

sort (height, height + N);

total = 0;

for (int i = 0; i < N; i++)


{
// query the largest index satisfying the conditions
int ind = binsearch (H - height [i]);

// only count if ind > i


if (ind > i)
total += ind - i;
else break;
}

fprintf (fout, "%d\n", total);

return 0;
}

Election Time [Jeffrey Wang, 2007]

The cows are having their first election after overthrowing the tyrannical
Farmer John, and Bessie is one of N cows (1 <= N <= 50,000) running for
President. Before the election actually happens, however, Bessie wants to
determine who has the best chance of winning.

The election consists of two rounds. In the first round, the K cows (1 <= K <=
N) cows with the most votes advance to the second round. In the second round,
the cow with the most votes becomes President.

Given that cow i expects to get A i votes (1 <= Ai <= 1,000,000,000) in the
first round and Bi votes (1 <= Bi <= 1,000,000,000) in the second round (if he
or she makes it), determine which cow is expected to win the election. Happily
for you, no vote count appears twice in the A i list; likewise, no vote count
appears twice in the Bi list.

INPUT FORMAT:
* Line 1: Two space-separated integers: N and K

* Lines 2..N+1: Line i+1 contains two space-separated integers: A i and Bi

SAMPLE INPUT (file elect.in):

5 3
3 10
9 2
5 6
8 4
6 5

INPUT DETAILS:

There are 5 cows, 3 of which will advance to the second round. The cows expect
to get 3, 9, 5, 8, and 6 votes, respectively, in the first round and 10, 2, 6,
4, and 5 votes, respectively, in the second.

OUTPUT FORMAT:

* Line 1: The index of the cow that is expected to win the election.

SAMPLE OUTPUT (file elect.out):

OUTPUT DETAILS:

Cows 2, 4, and 5 advance to the second round; cow 5 gets 5 votes in the
second round, winning the election.

Problem where the goal is simply to follow the rules of the task description.
This one is slightly complex owing to the requirement for a 'sort' routine. C
and C++ programmers have easily used built-in sort routines (e.g., qsort).

Furthermore, the sort routine has to be able to sort one number while carrying
two other numbers in the exchanges. The program below is a simple
demonstration of how qsort can be used to perform such operations. Java and
Pascal programmers had merely to augment their variable-swap routines to swap
three variables. Some folks wrote two separate but similar sort routines; some
used an if statement to differentiate variable for testing.

Complete credit relied on an O(N logN) solution; O(N2) sorts were not fast
enough to get full points.

#include <stdio.h>
#include <stdlib.h>
struct vote_f {
int a;
int b;
int cownum;
} votes[50000];

comparea (struct vote_f *a, struct vote_f *b) { return b->a - a->a; }
compareb (struct vote_f *a, struct vote_f *b) { return b->b - a->b; }

main() {
FILE *fin = fopen ("elect.in", "r");
FILE *fout = fopen ("elect.out", "w");
int n, k, i;

fscanf (fin, "%d %d", &n, &k);


for (i = 0; i < n; i++) {
fscanf (fin, "%d %d", &votes[i].a, &votes[i].b);
votes[i].cownum = i;
}
qsort(votes, n, sizeof (struct vote_f), comparea);
qsort(votes, k, sizeof (struct vote_f), compareb);
fprintf (fout, "%d\n", votes[0].cownum+1);
exit (0);
}

iCow [Jeffrey Wang, 2008]

Fatigued by the endless toils of farming, Farmer John has decided to try his
hand in the MP3 player market with the new iCow. It is an MP3 player that
stores N songs (1 <= N <= 1,000) indexed 1 through N that plays songs in a
"shuffled" order, as determined by Farmer John's own algorithm:

* Each song i has an initial rating R i (1 <= Ri <= 10,000).

* The next song to be played is always the one with


the highest rating (or, if two or more are tied, the highest
rated song with the lowest index is chosen).

* After being played, a song's rating is set to zero, and its rating
points are distributed evenly among the other N-1 songs.

* If the rating points cannot be distributed evenly (i.e.,


they are not divisible by N-1), then the extra points are
parceled out one at a time to the first songs on the list
(i.e., R_1, R_2, etc. -- but not the played song) until no
more extra points remain.

This process is repeated with the new ratings after the next song is played.

Determine the first T songs (1 <= T <= 1000) that are played by the iCow.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and T

* Lines 2..N+1: Line i+1 contains a single integer: R i

SAMPLE INPUT (file icow.in):

3 4
10
8
11

INPUT DETAILS:

The iCow contains 3 songs, with ratings 10, 8, and 11, respectively. You must
determine the first 4 songs to be played.

OUTPUT FORMAT:

* Lines 1..T: Line i contains a single integer that is the i-th song
that the iCow plays.

SAMPLE OUTPUT (file icow.out):

3
1
2
3

OUTPUT DETAILS:

The ratings before each song played are:


R_1 R_2 R_3
10 8 11 -> play #3 11/2 = 5, leftover = 1
16 13 0 -> play #1 16/2 = 8
0 21 8 -> play #2 21/2 = 10, leftover = 1
11 0 18 -> play #3 ...
This program is a "pure programming" task. It requires nothing more than the
implementation of a set of rules. The example even showed how one of the
potentially troublesome rules actually worked.

The program below is commented to show how each step is performed. The only
potentially tricky part is the use of two variables for the distribution: one
to count how many pieces get distributed and the second to say where they go.
The second variable is the trick for implementing the "Don't redistribute back
to the currently playing song" rule.

#include <stdio.h>
#include <stdlib.h>

void main() {
int bestrate, bestj, i, j, k, n, t, r[1000+1];
int evenlydistribute, leftover;
FILE *fin = fopen ("icow.in", "r");
FILE *fout = fopen ("icow.out", "w");

fscanf (fin, "%d %d", &n, &t);

for (i = 0; i < n; i++)


fscanf (fin, "%d", &r[i]);

for (i = 0; i < t; i++) { /* play t songs */


/* find highest rated song */
bestrate = -1;
for (j = 0; j < n; j++) {
if (r[j] > bestrate) { /* best, lowest index */
bestj = j;
bestrate = r[j];
}
}
fprintf (fout, "%d\n", bestj+1); /* play it */
evenlydistribute = r[bestj]/(n-1);
leftover = r[bestj] % (n-1);
r[bestj] = 0;
for (j = 0; j < n; j++)
if (j != bestj)
r[j] += evenlydistribute;
for (k = j = 0; j < leftover; j++, k++) {
if (j == bestj) k++;
r[k]++;
}
}
}

SILVER PROBLEMS
**********************************************************************

Cow Contest [Neal Wu, 2007]

N (1 <= N <= 100) cows, conveniently numbered 1..N, are participating in a


programming contest. As we all know, some cows code better than others. Each
cow has a certain constant skill rating that is unique among the competitors.

The contest is conducted in several head-to-head rounds, each between two


cows. If cow A has a greater skill level than cow B (1 <= A <= N; 1 <= B <= N;
A != B), then cow A will always beat cow B.

Farmer John is trying to rank the cows by skill level. Given a list the
results of M (1 <= M <= 4,500) two-cow rounds, determine the number of cows
whose ranks can be precisely determined from the results. It is guaranteed
that the results of the rounds will not be contradictory.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Each line contains two space-separated integers that


describe the competitors and results (the first integer, A, is the winner) of
a single round of competition: A and B

SAMPLE INPUT (file contest.in):

5 5

4 3

4 2

3 2

1 2
2 5

OUTPUT FORMAT:

* Line 1: A single integer representing the number of cows whose ranks

can be determined

SAMPLE OUTPUT (file contest.out):

OUTPUT DETAILS:

Cow 2 loses to cows 1, 3, and 4. Thus, cow 2 is no better than any of the cows
1, 3, and 4. Cow 5 loses to cow 2, so cow 2 is better than cow 5. Thus, cow 2
must be fourth, and cow 5 must be fifth. The ranks of the other cows cannot be
determined.

First, note that the problem can be converted into a graph, with the cows as
the nodes, and the games as the edges. (In particular, note that the graph is
a directed acyclic graph, or a DAG.)

For a certain cow X, X's rank can be determined if and only if the following
property is true: for every other cow Y, either cow X must be better than cow
Y, or cow Y must be better than cow X.

Thus, we can find which pairs of vertices in the graph are connected either by
doing a BFS for O(NM) overall or Floyd-Warshall for O(N 3) overall. Then, for
each cow, we check if every other cow is connected to it, and if so, we
increment our answer by 1.

The following is a sample solution:

#include <cstdio>
using namespace std;
FILE *fout = fopen ("contest.out", "w");
FILE *fin = fopen ("contest.in", "r");

const int MAXN = 105;

int N, M, total = 0;
bool reach [MAXN][MAXN];

void main ()
{
fscanf (fin, "%d %d", &N, &M);

// cows are 'connected' to themselves


for (int i = 0; i < N; i++)
reach [i][i] = true;

// read input
int a, b;
for (int i = 0; i < M; i++)
{
fscanf (fin, "%d %d", &a, &b);
a--, b--;

reach [a][b] = true;


}

// use Floyd-Warshall to compute transitive closure


for (int k = 0; k < N; k++)
for (int i = 0; i < N; i++)
if (reach [i][k])
for (int j = 0; j < N; j++)
if (reach [k][j])
reach [i][j] = true;

for (int i = 0; i < N; i++)


{
bool good = true;

// we can find the rank of a cow if all other cows are connected to it
for (int j = 0; j < N; j++)
if (!reach [i][j] && !reach [j][i])
{
good = false;
break;
}

if (good)
total++;
}

fprintf (fout, "%d\n", total);


}

Running [Neal Wu, 2007]

The cows are trying to become better athletes, so Bessie is running on a track
for exactly N (1 <= N <= 10,000) minutes. During each minute, she can choose
to either run or rest for the whole minute.

The ultimate distance Bessie runs, though, depends on her 'exhaustion factor',
which starts at 0. When she chooses to run in minute i, she will run exactly a
distance of Di (1 <= Di <= 1,000) and her exhaustion factor will increase by 1
-- but must never be allowed to exceed M (1 <= M <= 500). If she chooses to
rest, her exhaustion factor will decrease by 1 for each minute she rests. She
cannot commence running again until her exhaustion factor reaches 0. At that
point, she can choose to run or rest.

At the end of the N minute workout, Bessie's exaustion factor must be exactly
0, or she will not have enough energy left for the rest of the day.

Find the maximal distance Bessie can run.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and M


* Lines 2..N+1: Line i+1 contains the single integer: D i

SAMPLE INPUT (file cowrun.in):

5 2

10

OUTPUT FORMAT:

* Line 1: A single integer representing the largest distance Bessie can run
while satisfying the conditions.

SAMPLE OUTPUT (file cowrun.out):

OUTPUT DETAILS:

Bessie runs during the first minute (distance=5), rests during the second
minute, runs for the third (distance=4), and rests for the fourth and fifth.
Note that Bessie cannot run on the fifth minute because she would not end with
a rest factor of 0.

This is a straightforward dynamic programming (DP) problem. To solve the


problem, we want to find, for each k such that 0 <= k <= N, the maximum
possible distance Bessie could have run after the first k minutes, if she has
a rest factor of 0. (For example, if we can obtain a distance of 14 after 5
minutes with a rest factor of 0, or we can obtain a distance of 15 after 5
minutes with a rest factor of 0, we would always choose the second over the
first.) Clearly, the best such value for 0 is 0. Then, for each minute i of
the N minutes, we can compute all of the next values possible with the
following method:

-First, try to not run during the minute, and see if this produces an
improvement. (Thus, check if the best value for i is better than the one for i
+ 1.)

-Then, for each number k from 1 to M, let Bessie run for exactly k minutes and
then rest for k minutes. See if this new value produces a greater value than
the best value for i + 2k (which is the number of minutes finished after
running for k minutes and resting for another k minutes).

Thus, since we do M updates for each of the N minutes, our total complexity is
O(NM). The following is a sample solution:

#include <cstdio>
using namespace std;

FILE *fout = fopen ("cowrun.out", "w");


FILE *fin = fopen ("cowrun.in", "r");

const int MAXN = 10005;

int N, M, dist [MAXN], best [MAXN];

void main ()
{
fscanf (fin, "%d %d", &N, &M);

for (int i = 0; i < N; i++)


fscanf (fin, "%d", dist + i);

for (int i = 0; i < N; i++)


{
// skip the value
if (best [i] > best [i + 1])
best [i + 1] = best [i];

int sum = best [i], pos = i;

for (int j = 0; j < M && pos < N; j++)


{
// update each value
sum += dist [i + j];
pos += 2;
if (sum > best [pos])
best [pos] = sum;
}
}

fprintf (fout, "%d\n", best [N]);


}

Telephone Lines [Paul Christiano, 2007]

Farmer John wants to set up a telephone line at his farm. Unfortunately, the
phone company is uncooperative, so he needs to pay for some of the cables
required to connect his farm to the phone system.

There are N (1 <= N <= 1,000) forlorn telephone poles conveniently numbered
1...N that are scattered around Farmer John's property; no cables connect any
them. A total of P (1 <= P <= 10,000) pairs of poles can be connected by a
cable; the rest are too far apart.

The ith cable can connect the two distinct poles A i and Bi, with length Li (1
<= L_i <= 1,000,000) units if used. The input data set never names any {A i,Bi}
pair more than once. Pole 1 is already connected to the phone system, and pole
N is at the farm. Poles 1 and N need to be connected by a path of cables; the
rest of the poles might be used or might not be used.

As it turns out, the phone company is willing to provide Farmer John with K (0
<= K < N) lengths of cable for free. Beyond that he will have to pay a price
equal to the length of the longest remaining cable he requires (each pair of
poles is connected with a separate cable), or 0 if he does not need any
additional cables.

Determine the minimum amount that Farmer John must pay.

INPUT FORMAT:
* Line 1: Three space-separated integers: N, P, and K

* Lines 2..P+1: Line i+1 contains the three space-separated integers:

Ai, Bi, and Li

SAMPLE INPUT (file phoneline.in):

5 7 1

1 2 5

3 1 4

2 4 8

3 2 3

5 2 9

3 4 7

4 5 6

INPUT DETAILS:

There are 5 poles. Pole 1 cannot be connected directly to poles 4 or 5. Pole 5


cannot be connected directly to poles 1 or 3. All other pairs can be
connected. The phone company will provide one free cable.

OUTPUT FORMAT:

* Line 1: A single integer, the minimum amount Farmer John can pay. If it is
impossible to connect the farm to the phone company, print -1.

SAMPLE OUTPUT (file phoneline.out):


4

OUTPUT DETAILS:

If pole 1 is connected to pole 3, pole 3 to pole 2, and pole 2 to pole 5 then


Farmer John requires cables of length 4, 3, and 9. The phone company will
provide the cable of length 9, so the longest cable needed has length 4.

We construct the following graph G: each pole is a vertex, and each possible
connection between poles is an edge between corresponding vertices with weight
equal to the distance between the poles.

Now imagine we have a function f(lim) that tells us if there exists a path
from vertex 1 to vertex N using no more than K edges whose weights are greater
than lim. If we have such a function f, we can perform a binary search for the
answer: the smallest lim that works (in other words, the smallest k such that
f(k) is true) is the minimum amount Farmer John must pay.

So the problem now is implementing function f(lim) efficiently, and to do so,


we consider the graph H, which has the same vertices and edges as G but
different edge weights. More precisely, an edge between vertices a and b in H
has weight 0 if the corresponding edge in G has weight w <= lim, and weight 1
otherwise (if the corresponding edge in G has weight w > lim), so the shortest
path between two vertices a and b in H represents the minimum number of edges
with weight greater than lim on a path between a and b in G. Thus computing
f(lim) is equivalent to checking if the shortest path between 1 and N in H is
less than or equal to K, and we can do this in O(E log V) time with
Dijkstra's.

In the worst case, we will need to evaluate function f O(log V) times (because
of the binary search), so the total running time of the entire algorithm is
O(E log2 V). (It's actually possible to compute the shortest path between two
vertices in a graph where all edges have weight 0 or 1 in linear time, but
that's not needed here.)

#include<fstream>
#include<vector>

using namespace std;

ifstream fin ("phoneline.in");


ofstream fout ("phoneline.out");
const int MAX = 1000 + 5;

vector <int> a[MAX], b[MAX];


int e[MAX * 10];
bool mark[MAX];
int dis [MAX], saf[MAX], head, tail;
int n, k, D, M;

void dfs (int u)


{
dis[u] = D;
mark[u] = true;
saf[tail++] = u;
for (int i = 0; i < a[u].size (); i++) {
if (!mark[a[u][i]] && b[u][i] <= M)
dfs (a[u][i]);
}
}
void Bfs (int MM)
{
M = MM;
memset (mark, 0, sizeof mark);
head = tail = 0;
D = 0;
dfs (n - 1);
while (head < tail) {
int k = saf[head++];
for (int i = 0; i < a[k].size (); ++i) {
if (!mark[a[k][i]]) {
D = dis[k] + 1;
dfs (a[k][i]);
}
}
}
}

void bs (int x, int y)


{
if (y == x + 1) {
fout << e[y] << endl;
exit (0);
}
int mid = (y + x) / 2;
Bfs (e[mid]);
if (dis[0] <= k)
bs (x, mid);
else
bs (mid, y);
}
void main ()
{
int ee;
fin >> n >> ee >> k;
int u, v, w;
for (int i = 0; i < ee; ++i) {
fin >> u >> v >> w;
u--;
v--;
a[u].push_back (v);
b[u].push_back (w);
a[v].push_back (u);
b[v].push_back (w);
e[i + 1] = w;
}
sort (e, e + 1 + ee);
Bfs (0);
if (!mark[0]) {
fout << "-1" << endl;
return 0;
}
if (dis[0] <= k) {
fout << "0" << endl;
return 0;
}
bs (0, ee);
}

GOLD PROBLEMS

*****************************************************************************

Haybale Guessing [Brian Dean, 2003]

The cows, who always have an inferiority complex about their intelligence,
have a new guessing game to sharpen their brains.
A designated 'Hay Cow' hides behind the barn and creates N (1 <= N <=
1,000,000) uniquely-sized stacks (conveniently numbered 1..N) of hay bales,
each with 1..1,000,000,000 bales of hay.

The other cows then ask the Hay Cow a series of Q (1 <= Q <= 25,000) questions
about the the stacks, all having the same form:

What is the smallest number of bales of any stack in the range of stack
numbers Ql..Qh (1 <= Ql <= N; Ql <= Qh <= N)?

The Hay Cow answers each of these queries with a single integer A whose
truthfulness is not guaranteed.

Help the other cows determine if the answers given by the Hay Cow are self-
consistent or if certain answers contradict others.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and Q

* Lines 2..Q+1: Each line contains three space-separated integers that


represent a single query and its reply: Q l, Qh, and A

SAMPLE INPUT (file bales.in):

20 4

1 10 7

5 19 7

3 12 8

11 15 12
INPUT DETAILS:

The minimum number of bales in stacks 1..10 is 7, the minimum number of bales
in stacks 5..19 is 7, the minimum number of bales in stacks 3..12 is 8, and
the minimum number of bales in stacks 11..15 is 12.

OUTPUT FORMAT:

* Line 1: Print the single integer 0 if there are no inconsistencies

among the replies (i.e., if there exists a valid realization

of the hay stacks that agrees with all Q queries). Otherwise,

print the index from 1..Q of the earliest query whose answer

is inconsistent with the answers to the queries before it.

SAMPLE OUTPUT (file bales.out):

OUTPUT DETAILS:

Query 3 ("3 12 8") is the first that is inconsistent with those before it.
From queries 1 and 2 and the fact that all hay stacks have a distinct number
of bales, we deduce that one of stacks 5..10 must contain exactly 7 bales.
However, this stack contradicts the answer to query 3.

The first (and most crucial) observation to make is that if there exists a
list of stack sizes that satisfies queries 1...m, then the same set satisfies
queries 1...m-1. So we can perform binary search on the biggest sequence of
queries that can be satisfied, and reduce the problem to finding whether a set
of queries is satisfiable.

Then, given a sequence of query results, we can find out what's the lowest
number of bales in each stack in O(N+Q logQ) time by sweeping through the
queries and tracking the 'limiting query' using a heap. This can alternatively
be done using a range tree, although that's a bit slower.

We then need to check that minimum values are indeed present in the ranges.
For all the queries whose answer is x, the value x must be present in their
intersection since x can only appear once total. Then x must appear once as
one of the 'minimum' values since x is also an upper bound on that region as
well. So this can be checked in O(N) time using a lookup list as well. Note
that this condition is sufficient since all the other duplicated values (in
the lower bound list) can have their values rised to arbitrary values without
causing any further problems.

Below is Richard Peng's solution:

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

#define MAXN 1100000


#define MAXQ 30000

struct qtype {
int p1, p2, res, id;
bool operator < (const qtype & o)const { return p1 < o.p1; }
}lis[MAXQ];

pair <int, int> lis1[MAXQ];


int last[MAXQ], v[MAXN], left[MAXQ], right[MAXQ], n, q, needt;
priority_queue <pair <int, int> >lim;
pair <pair <int, int>, int> need[MAXQ];

int work (int len)


{
int i, i1, i2;
if (len > q) return 0;

while (!lim.empty ()) lim.pop ();

for (i = 0; i < q; i++)


{
left[i] = last[i] = 0;
right[i] = n;
}

for (i = 0; i < q; i++)


if (lis[i].id < len)
{
left[lis[i].res] >?= lis[i].p1;
right[lis[i].res] <?= lis[i].p2;
}

needt = 0;

for (i = 0; i < q; i++)


if (left[i] != 0)
{
need[needt].first.first = right[i];
need[needt].first.second = left[i];
need[needt++].second = i;
}

sort (need, need + needt);

for (i = 1, i1 = i2 = 0; i <= n; i++)


{
for (; (i1 < q) && (lis[i1].p1 == i); i1++)
if (lis[i1].id < len)
lim.push (pair < int, int >(lis[i1].res, lis[i1].p2));

while ((!lim.empty ()) && (lim.top ().second < i))


lim.pop ();

v[i] = lim.empty () ? 0 : v[i] = lim.top ().first;

last[v[i]] = i;

for (; (i2 < needt) && (need[i2].first.first == i); i2++)


if (last[need[i2].second] < need[i2].first.second)
return 0;
}

return 1;
}

void main ()
{
int i, j, tot, ans, del;
freopen ("bales.in", "r", stdin);
freopen ("bales.out", "w", stdout);
scanf ("%d%d", &n, &q);

for (i = 0; i < q; i++)


{
scanf ("%d%d%d", &lis[i].p1, &lis[i].p2, &lis[i].res);
lis[i].id = i;
lis1[i].first = lis[i].res;
lis1[i].second = i;
}

sort (lis1, lis1 + q);

for (i = tot = 0; i < q; i++)


{
tot += ((i == 0) || (lis1[i].first != lis1[i - 1].first));
lis[lis1[i].second].res = tot;
}

sort (lis, lis + q);

for (del = 1 << 16, ans = 0; del; del /= 2)


if (work (ans + del))
ans += del;
printf ("%d\n", (ans < q) ? (ans + 1) : 0);

Arti icial Lake [Matt McCutchen, 2006]

The oppressively hot summer days have raised the cows' clamoring to its
highest level. Farmer John has finally decided to build an artificial lake.
For his engineering studies, he is modeling the lake as a two-dimensional
landscape consisting of a contiguous sequence of N soon-to-be-submerged levels
(1 <= N <= 100,000) conveniently numbered 1..N from left to right.

Each level i is described by two integers, its width W_i (1 <= W i <= 1,000)
and height (like a relative elevation) Hi (1 <= Hi <= 1,000,000). The heights
of FJ's levels are unique. An infinitely tall barrier encloses the lake's
model on the left and right. One example lake profile is shown below.

* * :
* * :

* * 8

* *** * 7

* *** * 6

* *** * 5

* ********** 4 <- height

* ********** 3

*************** 2

*************** 1

Level | 1 |2| 3 |

In FJ's model, he starts filling his lake at sunrise by flowing water into the
bottom of the lowest elevation at a rate of 1 square unit of water per minute.
The water falls directly downward until it hits something, and then it flows
and spreads as room-temperature water always does. As in all good models,
assume that falling and flowing happen instantly. Determine the time at which
each elevation's becomes submerged by a single unit of water.

WATER WATER OVERFLOWS

| |

* | * * | * * *

* V * * V * * *

* * * .... * *~~~~~~~~~~~~*

* ** * *~~~~** : * *~~~~**~~~~~~*

* ** * *~~~~** : * *~~~~**~~~~~~*

* ** * *~~~~**~~~~~~* *~~~~**~~~~~~*

* ********* *~~~~********* *~~~~*********

*~~~~********* *~~~~********* *~~~~*********

************** ************** **************

************** ************** **************


After 4 mins After 26 mins After 50 mins

Lvl 1 submerged Lvl 3 submerged Lvl 2 submerged

Warning: The answer will not always fit in 32 bits.

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 describes level i with two space-separated

integers: Wi and Hi

SAMPLE INPUT (file alake.in):

4 2

2 7

6 4

INPUT DETAILS:

Three levels just as in the example above. Water will fill the first level
because it is the lowest.

OUTPUT FORMAT:

* Lines 1..N: Line i contains a single integer that is the number of


minutes that since sunrise when level #i is covered by water

of height 1.

SAMPLE OUTPUT (file alake.out):

50

26

We try to solve the problem for each level separately. For each level, the
amount of water required until it overflows can be broken down into three
parts. WOLOG, we assume the level is to the left of the level of minimum
height. The three parts are:

 To the left of the level. Water will flow this way unti it encounters
the first level that has a higher height. So, for each level, we need to
find the first level to its left that has a higher height. This can be
done using a stack in O(n) time.
 Between the level and the lowest level. The water levels forms a series
of 'steps', which can be tracked in a stack if we consider the levels
from right to left. This can also be calculated in O(n) time.
 To the right of the lowest level. If we consider the levels one by one
leftwards starting from the one to the left of the lowest level, the
water level at the lowest level can only increase. So it suffices to
keep a pointer to how far to the right gets submerged and increase this
counter as we go. This clearly also runs in O(n)

Combining these three parts, we get an O(n) algorithm. Many of the solutions
submitted by contestants used much cleverer algorithms that combines these
three steps into a single one, but most are still based on this 'step' idea.
Here is Neal Wu's explanation on how he did this problem:

Add in the two infinite barriers as 'levels' with infinite height for
simplicity. We will find the answer for each level in the order they are
filled, keeping track of the current time when calculating each.

Note that after we have filled level L, the water will go in the direction of
the shorter neighbor level of L. For example, in the following diagram, after
level 2 is filled, the water will flow to the right:

* * 8
* * 7
**** * 6
**** ** * 5 <-- heights
**** **** * 4
**** ******* * 3
**** ********* 2
*************** 1
1 2 3 4 5 6
Levels

The water will keep flowing to the right (and thus 'skipping' levels) until an
increase in height occurs. Thus, in the example above, level 6 will be filled
next after level 2 is finished.

Also, note that at this point both level 2 and level 3 share the same water
level. They will always remain at the same height since the water fills them
evenly. Thus, we can 'merge' level 2 into level 3 (the new width of level 3
will be the sum of its original width and the width of level 2), and delete
level 2. Note that to implement this merging efficiently we can use a linked
list of levels (which enables constant time deletion of a level).

This gives us a fairly simple algorithm: find the level which the water
currently fills (starting with the shortest level), and calculate the time at
which it becomes submerged (which is equal to the time when the level began to
fill up added to the width of the level). Next, find how long it takes for the
level to fill up to the height of the shorter of its two neighbors, and add
this to our current time. Finally, continue in the direction of the shorter
neighbor until we reach an increase in level heights. This level is the next
level to fill with water.

At first, it seems this approach is O(N 2), since we can skip up to O(N) levels
each time. However, the algorithm is actually linear time because of the
following fact: after we skip a level, we cannot skip it again. This is
because after a level is skipped, the water must come back to it from the
opposite direction, which means it must fill the level. (In the above example,
the water will skip level 5, fill level 6, and then come back to level 5 and
fill it.) Therefore each level can be skipped at most once, so the algorithm
takes O(N) time overall. The following is a sample implementation:

#include <cstdio>
using namespace std;

FILE *fin = fopen ("alake.in", "r");


FILE *fout = fopen ("alake.out", "w");

const int MAXN = 100005, INF = 1000000000;

int N, width [MAXN], height [MAXN];


int prev [MAXN], next [MAXN]; // simplified linked list
long long ans [MAXN], total = 0;

void main () {
fscanf (fin, "%d", &N);
height [0] = height [N + 1] = INF; // infinite walls

int ind = 1; // the current level being filled with water

for (int i = 1; i <= N; i++) {


fscanf (fin, "%d %d", width + i, height + i);
prev [i] = i - 1, next [i] = i + 1; // initialize

// ind starts as the shortest level


if (height [i] < height [ind])
ind = i;
}

// continue until the current level is one of the walls


while (height [ind] < INF)
{
// calculate our current index
ans [ind] = total + width [ind];
// delete the current index
next [prev [ind]] = next [ind], prev [next [ind]] = prev [ind];

// take the smaller of the neighbors


if (height [prev [ind]] < height [next [ind]])
{
// add the time taken to our current total
total += (long long) width [ind] * (height [prev [ind]] - height
[ind]);
// merge the levels together
width [prev [ind]] += width [ind];
ind = prev [ind];

// find the next index


while (ind > 0 && height [prev [ind]] < height [ind])
ind = prev [ind];
}
else
{ // do similarly for the other neighbor
total += (long long) width [ind] * (height [next [ind]] - height
[ind]);
width [next [ind]] += width [ind];
ind = next [ind];

while (ind <= N && height [next [ind]] < height [ind])
ind = next [ind];
}
}

for (int i = 1; i <= N; i++)


fprintf (fout, "%lld\n", ans [i]);

Cell Phone Network [Jeffrey Wang, 2007]

Farmer John has decided to give each of his cows a cell phone in hopes to
encourage their social interaction. This, however, requires him to set up cell
phone towers on his N (1 <= N <= 10,000) pastures (conveniently numbered 1..N)
so they can all communicate.

Exactly N-1 pairs of pastures are adjacent, and for any two pastures A and B
(1 <= A <= N; 1 <= B <= N; A != B) there is a sequence of adjacent pastures
such that A is the first pasture in the sequence and B is the last. Farmer
John can only place cell phone towers in the pastures, and each tower has
enough range to provide service to the pasture it is on and all pastures
adjacent to the pasture with the cell tower.

Help him determine the minimum number of towers he must install to provide
cell phone service to each pasture.

PROBLEM NAME: tower

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N: Each line specifies a pair of adjacent pastures with two space-
separated integers: A and B

SAMPLE INPUT (file tower.in):


5

1 3

5 2

4 3

3 5

INPUT DETAILS:

Farmer John has 5 pastures: pastures 1 and 3 are adjacent, as are pastures 5
and 2, pastures 4 and 3, and pastures 3 and 5. Geometrically, the farm looks
like this (or some similar configuration)

4 2

| |

1--3--5

OUTPUT FORMAT:

* Line 1: A single integer indicating the minimum number of towers to

install

SAMPLE OUTPUT (file tower.out):

OUTPUT DETAILS:

The towers can be placed at pastures 2 and 3 or pastures 3 and 5.


This problem, known as the "minimum dominating set problem" in a tree, has a
nice greedy solution. Note that the graph in the problem is indeed a tree
because it has V-1 edges. We say a vertex is dominated by a set of vertices if
it is either in the set or adjacent to a vertex in the set. The algorithm is
as follows:

(1) Keep track of a set of vertices S.


(2) Root the tree at an arbitrary node.
(3) Visit the vertices of the tree with a postorder traversal.
(4) At each vertex, if it is not dominated by S, add it and all of its
neighbors to S.
(5) Once the traversal is done, visit the vertices in S in the reverse order
that they were added.
(6) At each vertex, if S is still a dominating set when the vertex is removed,
then do so.

The vertices left in S form a minimum dominating set. For a proof of why this
works, see http://www.cs.clemson.edu/~bcdean/greedy_tree_dom.swf.

Note that the running time of this algorithm is very good, O(N), since each
vertex is visited once in the postorder traversal and each vertex is added to
S at most once. Checking whether a vertex can be removed can also be done
efficiently by keeping track of how many vertices in S it is adjacent to. An
implementation of this algorithm is shown below.

#include <stdio.h>
#include <iostream>
#include <vector>

using namespace std;

int N, c[10100], p[10100];


vector <vector <int> > E;
vector <int> B;

void traverse(int v)
{
for(int i=0; i<E[v].size(); i++)
if(p[v] != E[v][i])
{
p[E[v][i]] = v;
traverse(E[v][i]);
}

if(c[v] == 0)
{
B.push_back(v);
c[v]++;
for(int i=0; i<E[v].size(); i++)
{
c[E[v][i]] += 2; B.push_back(E[v][i]);

for(int j=0; j<E[E[v][i]].size(); j++)


c[E[E[v][i]][j]]++;
}
}
}

void main()
{
FILE* in = fopen("tower.in", "r");
FILE* out = fopen("tower.out", "w");

fscanf(in, "%d", &N);


E.resize(N);
for(int i=0; i<N; i++) { p[i] = -1; c[i] = 0; }

int u, v;

for(int i=0; i<N-1; i++)


{
fscanf(in, "%d %d", &u, &v);
E[u-1].push_back(v-1);
E[v-1].push_back(u-1);
}

traverse(0);

int numRemove = 0;
for(int i=B.size()-1; i>=0; i--)
{
bool canRemove = (c[B[i]] > 1);

for(int j=0; j<E[B[i]].size(); j++)


canRemove = canRemove && (c[E[B[i]][j]] > 1);

if(canRemove)
{
c[B[i]]--;
for(int j=0; j<E[B[i]].size(); j++)
c[E[B[i]][j]]--;
}
numRemove += canRemove;
}

fprintf(out, "%d\n", B.size()-numRemove);


}
Special 2007 Chinese Competition contest

GOLD PROBLEMS

*****************************************************************************

Summing Sums [Neal Wu, 2007]

The N (1 <= N <= 50,000) cows, conveniently numbered 1..N, are trying to learn
some encryption algorithms. After studying a few examples, they have decided
to make one of their own! However, they are not very experienced at this, so
their algorithm is very simple:

Each cow i is given a starting number C i (0 <= Ci < 90,000,000), and then all
the cows perform the following process in parallel:

* First, each cow finds the sum of the numbers of the other N-1

cows.

* After all cows are finished, each cow replaces her number

with the sum she computed. To avoid very large numbers, the

cows will keep track of their numbers modulo 98,765,431.

They told Canmuu the moose about it in November; he was quite impressed.

Then one foggy Christmas Eve, Canmuu came to say: "Your algorithm is too easy
to break! You should repeat it T (1 <= T <= 1,414,213,562) times instead."
Obviously, the cows were very frustrated with having to perform so many
repetitions of the same boring algorithm, so after many hours of arguing,
Canmuu and the cows reached a compromise: You are to calculate the numbers
after the encryption is performed!

*Some extra feedback will be provided for the first 10 submissions to this
problem.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and T

* Lines 2..N+1: Line i+1 contains a single integer: C i

SAMPLE INPUT (file sumsums.in):

3 4

INPUT DETAILS:

Three cows, with starting numbers 1, 0, and 4; four repetitions of the


encryption algorithm.

OUTPUT FORMAT:

* Lines 1..N: Line i contains a single integer representing the number of cow
i (modulo 98,765,431) at the end of the encryption.
SAMPLE OUTPUT (file sumsums.out):

26

25

29

OUTPUT DETAILS:

The following is a table of the cows' numbers for each turn:

Cows' numbers

Turn Cow1 Cow2 Cow3

0 1 0 4

1 4 5 1

2 6 5 9

3 14 15 11

4 26 25 29

Let S be the sum of all the numbers at the beginning. We can construct a table
of the value of each cow's numbers after each turn:

Turn Cow i's number Sum of all cows' numbers

0 Ci S

1 S - Ci (n - 1) * S

2 (n - 2) * S + Ci (n - 1)2 * S

3 (n2 - 3n + 3) * S + Ci (n - 1)3 * S

In particular, note that the coefficient of S in cow i's number on the t-th
turn is (n - 1)t - 1 - (n - 1)t - 2 + (n - 1)t - 3 - ... ± (n - 1)1 ∓ (n - 1)0, and
the coefficient of Ci is (-1)t. (Both of these statements can be proven by
induction.)

Now, all we need to do to solve the problem is evaluate this sum (modulo
98,765,431). However, the sum can have 1 billion terms, so we need to find an
efficient way of doing this. Two possible methods, that can both be
implemented in O(log t), are described below:

The first is to evaluate the sum somewhat directly. Note that (n - 1) t - 1 - (n


- 1)t - 2 + (n - 1)t - 3 - (n - 1)t - 4 + ... ± (n - 1)1 ∓ (n - 1)0 = (n - 2) * (n -
1)t - 2 + (n - 2) * (n - 1) t - 4 + ..., with two possible endings for the sum
depending on whether t is even or odd. We can compute the value of the sum for
values of t that are powers of two, and then combine these values to find our
actual sum.

The second method is to find the sum using matrix powering. We note that on
each turn, the coefficient of S in each cow's number is multiplied by (n - 1),
and then 1 is either added to the coefficient or subtracted from it, depending
on whether t is even or odd. In order to simulate this using matrix powering,
we would like to create a 2-element vector V and a 2 x 2 matrix M such that V
[0] is the coefficient of S, and V [1] is either 1 or -1. Multiplying V by the
matrix M once should simulate one turn. In particular, we want to multiply V
[0] by n - 1, and then add V [1] to it, and we want to 'flip' V [1] between 1
and -1 each time. Thus, M should be the following matrix:

| n - 1 0 |

| |

| 1 -1 |

When V is multiplied by M, V [0] becomes (n - 1) * V [0] + 1 * V [1], and V


[1] becomes 0 * v [0] + (-1) * V [1], which was exactly what we wanted. Thus,
multiplying V by M a total of t times will suffice, but instead we can use
efficient O(log t) matrix powering to do this.

Two solutions are presented corresponding to the two methods given above. The
following is a power of two summation solution from Neal Wu:

#include <cstdio>
using namespace std;

FILE *fin = fopen ("sumsums.in", "r");


FILE *fout = fopen ("sumsums.out", "w");

const int MAXN = 50005, MAXL = 35;


const int MOD = 98765431;

int N, T, nums [MAXN];


long long power [MAXL], ssum [MAXL];

// computes A^(B - 1) - A^(B - 2) + ... +/- A -/+ 1


// by computing (A - 1) * A^(B - 2) + ...
// takes O(log B) time
long long calc (int A, int B)
{
power [0] = A % MOD;
ssum [0] = (A - 1) % MOD;

// power [i] = A^(2^i)


// ssum [i] = the sum of the first 2^i terms of the second sum above

for (int i = 0; i + 1 < MAXL; i++)


{
power [i + 1] = (power [i] * power [i]) % MOD;
ssum [i + 1] = (ssum [i] * power [i + 1] + ssum [i]) % MOD;
}

bool odd = (B & 1);


B >>= 1;

long long p = 1, total = 0;

for (int i = 0; (1 << i) <= B; i++)


if (B & (1 << i))
{
// combine the sums for each power of two in the binary representation of B
total = (total + ssum [i] * p) % MOD;
p = (p * power [i + 1]) % MOD;
}

// do a special case for odd B


if (odd)
total = (total * A + 1) % MOD;

return total;
}

Void main ()
{
fscanf (fin, "%d %d", &N, &T);

long long sum = 0;

for (int i = 0; i < N; i++)


{
fscanf (fin, "%d", nums + i);
sum += nums [i];
}

sum %= MOD;

int add = (sum * calc (N - 1, T)) % MOD;

for (int i = 0; i < N; i++)


fprintf (fout, "%d\n", (add + (T & 1 ? -nums [i] : nums [i]) + MOD) %
MOD);
}

The following is a matrix multiplication solution from Richard Peng:

#include <cstdio>
#include <cstring>

#define MAXN 50000


#define M 98765431

int res[2],v[2][2],tem[2][2],t,t1;
int lis[MAXN],dif[MAXN],n;
long long tot;

void mul(int a[2][2],int b[2][2]){


int i,j,k;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(tem[i][j]=0,k=0;k<2;k++)
tem[i][j]=(tem[i][j]+(long long)a[i][k]*b[k][j])%M;

void main(){
int i;
freopen("sumsums.in","r",stdin);
freopen("sumsums.out","w",stdout);
scanf("%d%d",&n,&t);
for(i=tot=0,0;i<n;i++){
scanf("%d",&lis[i]);
dif[i]=lis[i]-lis[0];
tot+=dif[i];
}
memset(v,0,sizeof(v));
memset(res,0,sizeof(res));
res[0]=lis[0]%M;
res[1]=tot%M;
v[0][0]=(n-1)%M;
v[0][1]=1;
v[1][1]=-1;
for(t1=t;t1;t1/=2){
if(t1%2){
res[0]=((long long)res[0]*v[0][0]+(long long)res[1]*v[0][1])
%M;
res[1]=((long long)res[1]*v[1][1])%M;
}
mul(v,v);
memcpy(v,tem,sizeof(v));
}
for(i=0;i<n;i++)
printf("%d\n",((res[0]+((t%2==0)?(dif[i]):(-dif[i])))%M+M)%M);}

The Bovine Accordion and Banjo Orchestra [Lei Huang, 2007]

The 2*N (3 <= N <= 1,000) cows have assembled the Bovine Accordion and Banjo
Orchestra! They possess various levels of skill on their respective
instruments: accordionist i has an associated talent level A i (0 <= Ai <=
1,000); banjoist j has an associated talent level B j(0 <= Bj <= 1,000).

The combined `awesomeness' of a pairing between cows with talents A i and Bj is


directly proportional to the talents of each cow in the pair so a concert with
those two cows will earn FJ precisely A i * Bj dollars in "charitable
donations". FJ wishes to maximize the sum of all revenue obtained by his cows
by pairing them up in the most profitable way.

Unfortunately, FJ's accordionists are a bit stuck up and stubborn. If


accordionist i is paired with banjoist j, then accordionists i+1..N refuse to
be paired with banjoists 1..j-1. This creates restrictions on which pairs FJ
can form. FJ thus realizes that in order to maximize his profits, he may have
to leave some cows unpaired.

To make matters worse, when one or more of the musicians is skipped, they will
be greatly upset at their wasted talent and will engage in massive binge
drinking to wash away their sorrows.

After all pairings are made, a list is constructed of the groups of each of
the consecutive skipped musicians (of either instrument). Every group of one
or more consecutive skipped cows will gather together to consume kegs of ice
cold orange soda in an amount proportional to the square of the sum of their
wasted talent.
Specifically, FJ has calculated that if the x-th to y-th accordionists are
skipped, they will consume precisely (A x + Ax+1 + Ax+2 + ... + Ay)2 dollars worth
of orange soda in the process of drinking themselves into oblivion. An
identical relationship holds for the banjoists. FJ realizes that he'll end up
getting stuck with the bill for his cows' drinking, and thus takes this into
account when choosing which pairings to make.

Find the maximum amount of total profit that FJ can earn after the
contributions are collected and the orange soda is paid for.

Memory Limit: 64MB

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains the single integer: A i

* Lines N+2..2*N+1: Line i+N+1 contains the single integer: B i

SAMPLE INPUT (file baabo.in):

1
INPUT DETAILS:

There are 6 cows: 3 accordionists and 3 banjoists. The accordionists have

talent levels (1, 1, 5), and the banjoists have talent levels (5, 1, 1).

OUTPUT FORMAT:

* Line 1: A single integer that represents the maximum amount of cash that FJ
can earn.

SAMPLE OUTPUT (file baabo.out):

17

OUTPUT DETAILS:

FJ pairs accordionist 3 with banjoist 1 to get earn A_3 * B_1 = 5 * 5 = 25 in


profit. He loses a total of (1 + 1)^2 + (1 + 1)^2 = 8 dollars due to the cost
of soda for his remaining cows. Thus his final (net) profit is 25

- 8 = 17.

Since the pairings cannot intersect, this problem can be solved using DP with
the state being the last 'pair' of accordionist and banjoist (denoted A and B
from here on). This gives O(N2) states and O(N2) state transitions for each
state as there are O(N2) possible previous pairs, the state transition
function is:

Best(i,j)=max{i1<i,j1<j|Best(i1,j1)-SQR(sum(A_i1...A_(i-1)))-
SQR(sum(B_j1...B_(j-1)))}+A_i*B_j

where SQR is the square of a number.


This gives an O(N4) solution, which we try to optimize all the way down to
O(N2). The first observation we make is we cannot skip cows in both A and B
when we go from the current pair to the previous one. This because pairing any
two from those skipped ones will increase the total profit. So this gives an
O(n^3) solution, sufficient to get 60% of the points.

Now we try to get down to O(N 2) by optimizing the state transition using
convexity. We first consider the case where no cows in A are skipped, or when
i1=i-1. So we need to find:

max{j1<j|Best(i-1,j)-SQR(sum(B_j1...B_(j-1))}+A_i*B_j

If we let SB denote the partial sum of the B array, then our transition
formula becomes:

max{j1<j|Best(i-1,j)-SQR(SB_(j-1)-SB(j1-1))}+A_i*B_j =max{j1<j|Best(i-1,j)-
SQR(SB_(j1-1))+2*SB_(j1-1)*SB_(j-1)}+A_i*B_j+SQR(SB_(j-1))

We can ignore the last two terms since they're constant depending only on i
and j. If we look at the first term, we're looking for the max of a linear
combination of two values depending on j1 where the ratio is dependent on j.

Geometrically, this is equivalent to taking the y-intercept of a line with a


given slope within a set of points. With some proof, it can be shown that only
points on the convex hull matters. So we can insert values of (2*SB_j,Best(i-
1,j)-SQR(SB_(j-1)))) into the convex hull (note SB_j is always increasing, so
we can do this using a stack). And when we query, we can show the point where
this value is minimized/maximized is always monotone in respect to x. This
gives an algorithm that does this in O(1) amortized cost.

The case where nothing in B is skipped can be dealt with similarly. The only
catch is that should we process the states in incremental i and then
incremental j, we'll need to keep track of N+1 convex hulls, one for the
previous 'row' and one for each of the columns.

This gives the desired O(N2) algorithm.

#include <cstdio>
#include <cstring>

#define MAXN 1200

int n;
double a[MAXN],b[MAXN],bes[MAXN][MAXN],ans;
double s1[MAXN],s2[MAXN];

double sqr(double x){return x*x;}

double hull[MAXN][MAXN][2];
int hullt[MAXN],p[MAXN];

void initialize(int id){


hullt[id]=p[id]=0;
}

double crossp(double a[2],double b[2],double c[2]){


return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1]);
}

void hulladd(int id,double x,double y){


double point[2];
point[0]=x;
point[1]=y;
if((hullt[id]>0)&&(x==hull[id][hullt[id]-1][0])){
if(y>hull[id][hullt[id]-1][1]) hullt[id]--;
else return;
}
while((hullt[id]>1)&&(crossp(point,hull[id][hullt[id]-1],hull[id]
[hullt[id]-2])<=0))
hullt[id]--;
hull[id][hullt[id]][0]=x;
hull[id][hullt[id]][1]=y;
p[id]<?=hullt[id];
hullt[id]++;
}

double query(int id,double a){


double tem,tem1;
tem=hull[id][p[id]][0]*a+hull[id][p[id]][1];
while((p[id]+1<hullt[id])&&((tem1=(hull[id][p[id]+1][0]*a+hull[id][p[id]
+1][1]))>tem)){
tem=tem1;
p[id]++;
}
return tem;
}

void main()
{
int i,j,i1,j1;
freopen("mkpairs.in","r",stdin);
freopen("mkpairs.out","w",stdout);
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%lf",&a[i]);
for(s1[0]=a[0],i=1;i<n;i++) s1[i]=s1[i-1]+a[i];
for(i=0;i<n;i++) scanf("%lf",&b[i]);
for(s2[0]=b[0],i=1;i<n;i++) s2[i]=s2[i-1]+b[i];
memset(bes,0,sizeof(bes));

for(i=1;i<n;i++)
initialize(i);
for(ans=i=0;i<n;i++){
initialize(0);
for(j=0;j<n;j++){
bes[i][j]=-((i==0)?0:sqr(s1[i-1]))-((j==0)?0:sqr(s2[j-1]));

if(i>0){
if(j>0){
bes[i][j]>?=query(0,2*s2[j-1])-sqr(s2[j-1]);
bes[i][j]>?=query(j,2*s1[i-1])-sqr(s1[i-1]);
}
hulladd(0,s2[j],bes[i-1][j]-sqr(s2[j]));
}

bes[i][j]+=a[i]*b[j];
ans>?=bes[i][j]-sqr(s1[n-1]-s1[i])-sqr(s2[n-1]-s2[j]);
}
for(j=0;j+1<n;j++){
hulladd(j+1,s1[i],bes[i][j]-sqr(s1[i]));
}
}
printf("%0.0lf\n",ans);
}

Treasure [Yang Yi, 2007]

Canmuu and his friends have recently acquired a large cache of plutonium and
have agreed to bury their newfound treasure at some road intersection deep in
the Canadian wilderness. Any sort of treasure burial calls for a treasure map
so they've decided to create one of their own.

The road network consists of N (4 <= N <= 100,000) intersections (conveniently


numbered 1..N) with N roads connecting them. As busy intersections confuse
everybody, every intersection has at least one road that leads to it, and no
intersection has more than four roads connected to it. Excellent maintenance
has ensured that a moose can always run either way between any pair of
intersections. Furthermore, Canmuu has decided the plutonium should not be
buried at any of the 4-way intersections since busy traffic decreases the
secrecy of the buried treasure.
The treasure map will contain all the roads and all the intersections. But, to
conceal the treasure's location, only one road intersection on the treasure
map is to be labeled: the intersection at which the treasure is buried (which
has a big red 'X', of course).

Ever the alert moose, Canmuu drew some trial maps to see what they would look
like depending on where the treasure was buried. Canmuu noticed that the moose
might draw similar maps even if they bury their treasure in two different
locations. Their curiosity piqued, the herd began trying to figure out how
many distinct maps they could end up making.

Maps are indistinct if it is possible to assign a mapping such that:

* the X-labeled intersections on both maps correspond,

* a correspondence can be created for the other intersections,

such that

* when the well-chosen intersection correspondence is determined,

the roads that connect the intersections also correspond.

By way of example, consider the maps below where N = 4; the treasure might be
buried at any of four intersections:

+ + X +

/| /| /| /|

X---+ | +---X | +---+ | +---+ |

\| \| \| \|

+ + + X
The final two maps, however, are not distinct since one can create a
correspondence for the vertices (consider the map upside down) and then the
roads correspond exactly. Thus, only three maps are distinct.

How many distinct maps are possible for a given set of roads?

TIME LIMIT: 1 second; might be increased for big test cases

MEMORY LIMIT: 64MB

*Some extra feedback will be provided for the first 10 submissions to this
problem.

PROBLEM NAME: treasure

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N + 1: Two space-separated integers: A and B (1 <= A <= N;

1 <= B <= N), indicating that there is a road connecting

intersections A and B

SAMPLE INPUT (file treasure.in):

1 2

2 3

3 1
1 4

INPUT DETAILS:

Here is a drawing of the roads and the intersections.

4---1---2

\ /

OUTPUT FORMAT:

* Line 1: A single integer that is the number of distinct treasure

maps

SAMPLE OUTPUT (file treasure.out):

OUTPUT DETAILS:

The treasure can be buried at any intersection. However, burying it at


intersections 2 and 3 yields maps that are identical to each other. So the
total number of distinct treasure maps is 3.

To tackle this problem most effectively, we first establish that the road
network described in the problem is a cycle with trees 'coming off' it. So we
can root all the trees by the vertex they have on the cycle and denote nodes
by 'parent' and children'.
We essentially want to assign an 'id' to the graph surrounding each of the
vertices, which is a collection of several subtrees (its children) and a graph
that contains the cycle.

There are two ways of doing this, either by computing hash values for each
subgraph or by computing 'ids' as we proceed and only hash cyclic shifts of
the cycle. The first method is faster in practice and just accurate, but the
second is slightly easier to code due to usage of C++ STL.

Since a tree is a collection of its subtrees, we can assign 'id's to all the
subtrees rooted at each vertex by proceeding at the outermost layer and
proceed inwards.

Then we have to distinguish between all the cyclic shifts (with reflections)
of the cycles (which is how we could 'orient' the cycle with respect to the
tree the treasure is buried in). This can be accomplished by the standard
Rabin-Karp string hash, done once clockwise and once counter clockwise.

Then for each distinct tree, we can just count the trees that have distinct
ids by going down recursively, and when we're at a node, only count its
children that have distinct ids (so if two of its children have the same
subtree, only count one of them). This is correct since the 'root' is now a
special node (an orientation of the cycle).

This runs in O(N) time if hashing is used and O(NlogN) if set/map is used. The
test data were generated as follows:

Case 1: Sample.

Case 2: 3 chains with different lengths.

Case 3: random tree with edge

Case 4: random tree with edge

Case 5: 10 trees with AAABBCCCBB pattern, N = 53, the trees are specially
designed that they cover almost every simple cases.

Case 6: 50 same trees.

Case 7: 20 trees each with 20 nodes.

Case 8: random tree with edge

Case 9: Twin fibonacci trees.

Case 10: A sequence repeated 7 times.


Case 11: A cycle connected with a chain.

Case 12: Repeated ABCACBA pattern.

Case 13: Repeated AB pattern, changed one B into a special big tree.

Case 14: A sequence repeated 6 times with reflection.

Case 15: random tree with edge

#include <stdio.h>
#include <string.h>
#define maxn 100000
#define maxh 200003
#define maxH 1000000003LL

int ind[maxn], next[maxn * 2], to[maxn * 2], p;


int n;
int used[maxn];
int f;
int stack[maxn], sp;

int hash[maxh], hashans[maxh], hp;


int hashlib[maxh][3];
long long h1[maxn], h2[maxn];

long long hash2[maxh];

int addhash (int *data) {


long long c = 123456;
for (int i = 0; i < 3; i ++)
c = c * 47 ^ data[i];
c = c * 47 % maxh;
while (hash[c] != -1 && (hashlib[c][0] != data[0] || hashlib[c][1] !=
data[1] || hashlib[c][2] != data[2])) {
c ++;
if (c == maxh)
c = 0;
}
if (hash[c] == -1) {
hashlib[c][0] = data[0];
hashlib[c][1] = data[1];
hashlib[c][2] = data[2];
hash[c] = hp ++;
}
return hash[c];
}

int add2 (long long x, int i) {


long long c = x % maxh;
c = c * 47 % maxh;
while (hash2[c] != -1 && hash2[c] != x) {
c ++;
if (c == maxh)
c = 0;
}
if (hash2[c] == -1) {
hash2[c] = x;
hash[c] = i;
return -1;
}
else
return hash[c];
}

int test (int a, int b) {


for (int i = 0; i < sp; i ++)
if (stack[i + a >= sp? i + a - sp: i + a] != stack[i + b >= sp? i
+ b -
sp: i + b])
return 0;
return 1;
}

int dfs2 (int x, int dad) {

int lib[3], lp = 0;

for (int i = ind[x]; i != -1; i = next[i])


if (to[i] != dad && !used[to[i]])
lib[lp ++] = dfs2(to[i], x);
if (dad == -1)
lib[lp ++] = maxh - 2;
while (lp < 3)
lib[lp ++] = maxh - 1;
for (int i = 0; i < 3; i ++)
for (int j = 0; j < 2; j ++)
if (lib[j] > lib[j + 1])
lib[j] ^= lib[j + 1] ^= lib[j] ^= lib[j + 1];
lp = addhash(lib);
int ans = 0;
for (int i = 0; i < 3; i ++)
if (lib[i] != maxh - 1 && lib[i] != maxh - 2 && (i == 0
|| lib[i] !=
lib[i-1]))
ans += hashans[lib[i]];
if (lib[2] == maxh - 1)
ans ++;
hashans[lp] = ans;
return lp;
}

void dfs (int x, int dad) {


if (f)
return;
if (used[x] != 0xFEFEFEFE) {
f = 1;
sp = 0;
dad = to[dad];
stack[sp ++] = dad;
while (dad != x) {
dad = used[dad];
stack[sp ++] = dad;
}
return;
}
used[x] = dad == -1? -1 : to[dad];
for (int i = ind[x]; i != -1; i = next[i])
if (i != dad)
dfs(to[i], i^1);
}

int main () {
int i, a, b, c;

freopen("cowmstr.in", "r", stdin);


freopen("cowmstr.out", "w", stdout);

scanf("%d",&n);
p = 0;
memset(ind, -1, sizeof(ind));
for (i = 0; i < n; i ++) {
scanf("%d%d",&a,&b);
a --;
b --;

next[p] = ind[a];
to[p] = b;
ind[a] = p ++;

next[p] = ind[b];
to[p] = a;
ind[b] = p ++;
}

memset(used, -2, sizeof(used));


f = 0;
sp = 0;
dfs(0, -1);

memset(used, 0, sizeof(used));
for (i = 0; i < sp; i ++)
used[stack[i]] = 1;

/*
for (i = 0; i < sp; i ++)
printf("%d\n",stack[i]);
fflush(stdout);
*/

memset(hash, -1, sizeof(hash));


hp = 0;
for (i = 0; i < sp; i ++)
stack[i] = dfs2(stack[i], -1);

long long big = 1;


h1[0] = 0;
for (i = sp - 1; i >= 0; i --) {
h1[0] = (h1[0] * 147804523 + stack[i]) % maxH;
big = big * 147804523 % maxH;
}
for (i = sp - 1; i > 0; i --)
h1[i] = (h1[(i + 1) % sp] * 147804523 % maxH + stack[i] + maxH - big *
stack[i] % maxH) % maxH;

h2[0] = 0;
for (i = 1; i < sp; i ++)
h2[0] = (h2[0] * 147804523 + stack[i]) % maxH;
h2[0] = (h2[0] * 147804523 + stack[0]) % maxH;
for (i = 1; i < sp; i ++)
h2[i] = (h2[i - 1] * 147804523 % maxH + stack[i] + maxH - big *
stack[i] % maxH) % maxH;

memset(hash2, -1, sizeof(hash2));


a = -1;
for (i = 0; a == -1 && i < sp; i ++)
if ((b = add2(h1[i], i)) != -1)
if (test(b, i))
a = i - b;
if (a == -1)
a = sp;

b = 0;
c = 0;
for (i = 0; i < sp; i ++) {
if (h1[i] == h2[i]) {
b |= 1;
c = i;
}
if (h1[i] == h2[(i + 1) % sp] && !(b&1)) {
b |= 2;
c = (i + 1) % sp;
}
}
if (b & 1)
a = a / 2 + 1;
else
if (b & 2)
a = a / 2;
int ans = 0;

for (i = 0; i < a; i ++)


ans += hashans[stack[(i + c) % sp]];

printf("%d\n", ans);

Elite 2007 December Competition contest

BRONZE PROBLEMS

*****************************************************************************
Bookshelf [Neal Wu, 2007]

Farmer John recently bought a bookshelf for cow library, but the shelf is
getting filled up quite quickly, and now the only available space is at the
top.

Each of the N cows (1 <= N <= 20,000) has some height of H i (1 <= Hi <=
10,000) and a total height summed across all N cows of S. The bookshelf has a
height of B (1 <= B <= S < 2,000,000,007).

To reach the top of the bookshelf taller than the tallest cow, one or more of
the cows can stand on top of each other in a stack, so that their total height
is the sum of each of their individual heights. This total height must be no
less than the height of the bookshelf. Since more cows than necessary in the
stack can be dangerous, your job is to find the set of cows that produces a
stack of the smallest number of cows possible such that the stack can reach
the bookshelf.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and B

* Lines 2..N+1: Line i+1 contains a single integer: H i

SAMPLE INPUT (file shelf.in):

6 40

18

11

13
19

11

INPUT DETAILS:

Six cows; bookshelf height 40. Cow heights fall in the range 6..19.

OUTPUT FORMAT:

* Line 1: A single integer representing the size of the smallest set of cows
that can reach the bookshelf.

SAMPLE OUTPUT (file shelf.out):

OUTPUT DETAILS:

One way to reach 40 with 3 cows is 18+11+13; many others exist

Note that if it is possible to reach the bookshelf with a certain set of C


cows, then it must be possible with the C tallest cows. Thus, in order to
determine if it is possible to reach the bookshelf with C cows, we must check
only the C tallest cows. So we can loop over each C in increasing order, and
find the first C that satisfies the conditions.

To do this, we must sort the numbers in non-increasing order beforehand in O(N


log N) time, which can be done by either coding the sort yourself (using an
efficient sort such as quicksort or mergesort) or by using the provided
libraries. Afterward, loop over all k from 1 to N, until we find the first k
that produces a large enough sum. We must be careful to accumulate the sum
with our loop efficiently to avoid having an O(N 2) runtime.
With a properly-coded solution, the overall runtime will be O(N logN), as the
majority of the runtime comes from the initial sort. The following is a sample
solution:

#include <cstdio>
#include <algorithm>
using namespace std;

FILE *fout = fopen ("shelf.out", "w");


FILE *fin = fopen ("shelf.in", "r");

const int MAXN = 20005;

int N, B;
int heights [MAXN];

int solve () {
int sum = 0;

for (int i = 0; i < N; i++) {


sum += heights [i];
if (sum >= B)
return i + 1;
}
return -1; // should not happen
}

void main () {
fscanf (fin, "%d %d", &N, &B);
for (int i = 0; i < N; i++)
fscanf (fin, "%d", heights + i);

sort (heights, heights + N);


reverse (heights, heights + N);

fprintf (fout, "%d\n", solve ());


}

Bookshelf 2 [Neal Wu, 2007]


Farmer John recently bought another bookshelf for the cow library, but the
shelf is getting filled up quite quickly, and now the only available space is
at the top.

FJ has N cows (1 <= N <= 20) each with some height of H i (1 <= Hi <= 1,000,000
- these are very tall cows). The bookshelf has a height of B (1 <= B <= S,
where S is the sum of the heights of all cows).

To reach the top of the bookshelf, one or more of the cows can stand on top of
each other in a stack, so that their total height is the sum of each of their
individual heights. This total height must be no less than the height of the
bookshelf in order for the cows to reach the top.

Since a taller stack of cows than necessary can be dangerous, your job is to
find the set of cows that produces a stack of the smallest height possible
such that the stack can reach the bookshelf. Your program should print the
minimal 'excess' height between the optimal stack of cows and the bookshelf.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and B

* Lines 2..N+1: Line i+1 contains a single integer: H i

SAMPLE INPUT (file shelf2.in):

5 16

5
6

OUTPUT FORMAT:

* Line 1: A single integer representing the (non-negative) difference between


the total height of the optimal set of cows and the height of the shelf.

SAMPLE OUTPUT (file shelf2.out):

OUTPUT DETAILS:

Here we use cows 1, 3, 4, and 5, for a total height of 3 + 3 + 5 + 6 = 17. It


is not possible to obtain a total height of 16, so the answer is 1.

To solve this problem, we simply need to look at the sums of all 2 N subsets of
the numbers. (This is possible since N <= 20, and so there are at most around
one million such subsets.) There are several methods of doing this, but two
fairly simple methods are the following:

The first method is to iterate over all binary numbers from 0 to 2 N - 1,


inclusive. In each binary number, we can imagine it as having exactly N bits
(similar to base 10 'digits'). A '1' in bit number i means that we should use
cow i, while a '0' means that we should not. Thus, each binary number from 0
to 2N - 1 represents a subset of the N cows, and in fact they represent every
subset. This approach gives us a runtime of O(N 2 N).

The second method is to use recursion to generate every sum. For each cow, we
have two possibilities: we either use the cow or we don't. This gives us a
fairly simple solution that is O(2N) with a medium overhead of function calls.

Both the bitmask and the recursive solutions are presented:

#include <cstdio>
using namespace std;
FILE *fout = fopen ("shelf2.out", "w");
FILE *fin = fopen ("shelf2.in", "r");

const int INF = 1000000000;


const int MAXN = 25;

int N, B;
int heights [MAXN];
int sum, best = INF;

void main () {
fscanf (fin, "%d %d", &N, &B);

for (int i = 0; i < N; i++)


fscanf (fin, "%d", heights + i);

// iterate over every bitmask


for (int mask = 0; mask < (1 << N); mask++) {
sum = 0;
// calculate the sum of the subset
for (int i = 0; i < N; i++)
if (mask & (1 << i)) // is bit number i set?
sum += heights [i];

if (sum >= B && sum < best)


best = sum;
}

fprintf (fout, "%d\n", best - B);

#include <cstdio>
using namespace std;

FILE *fout = fopen ("shelf2.out", "w");


FILE *fin = fopen ("shelf2.in", "r");

const int INF = 1000000000;


const int MAXN = 25;

int N, B;
int heights [MAXN];
int best = INF;

void solve (int num, int sum) {


// update our best value
if (sum >= B && sum < best)
best = sum;

// either we are finished or our current sum is worse than the best so far
if (num == N || sum >= best)
return;

// two options - use the next number or not


solve (num + 1, sum + heights [num]);
solve (num + 1, sum);
}

void main ()
{
fscanf (fin, "%d %d", &N, &B);
for (int i = 0; i < N; i++)
fscanf (fin, "%d", heights + i);
solve (0, 0);
fprintf (fout, "%d\n", best - B);
}

Card Stacking [Jeffrey Wang, 2007]

Bessie is playing a card game with her N-1 (2 <= N <= 100) cow friends using a
deck with K (N <= K <= 100,000; K is a multiple of N) cards. The deck
contains M = K/N "good" cards and K-M "bad" cards. Bessie is the dealer and,
naturally, wants to deal herself all of the "good" cards. She loves winning.

Her friends suspect that she will cheat, though, so they devise a dealing
system in an attempt to prevent Bessie from cheating. They tell her to deal as
follows:

1. Start by dealing the card on the top of the deck to the cow

to her right

2. Every time she deals a card, she must place the next P (1 <=

P <= 10) cards on the bottom of the deck; and


3. Continue dealing in this manner to each player sequentially

in a counterclockwise manner

Bessie, desperate to win, asks you to help her figure out where she should put
the "good" cards so that she gets all of them. Notationally, the top card is
card #1, next card is #2, and so on.

PROBLEM NAME: cheat

INPUT FORMAT:

* Line 1: Three space-separated integers: N, K, and P

SAMPLE INPUT (file cheat.in):

3 9 2

INPUT DETAILS:

Bessie is playing cards with two cow friends and a deck of 9 cards. She must
place two cards on the bottom of the deck each time she deals one.

OUTPUT FORMAT:

* Lines 1..M: Positions from top in ascending order in which Bessie

should place "good" cards, such that when dealt, Bessie will

obtain all good cards.


SAMPLE OUTPUT (file cheat.out):

OUTPUT DETAILS:

Bessie should put the "good" cards in positions 3, 7, and 8. The cards will be
dealt as follows; the card numbers are "position in original deck":

Card Deck P1 P2 Bessie

Initial configuration 1 2 3 4 5 6 7 8 9 - - - - - - - - -

Deal top card [1] to Player 1 2 3 4 5 6 7 8 9 1 - - - - - - - -

Top card to bottom (#1 of 2) 3 4 5 6 7 8 9 2 1 - - - - - - - -

Top card to bottom (#2 of 2) 4 5 6 7 8 9 2 3 1 - - - - - - - -

Deal top card [4] to Player 2 5 6 7 8 9 2 3 1 - - 4 - - - - -

Top card to bottom (#1 of 2) 6 7 8 9 2 3 5 1 - - 4 - - - - -

Top card to bottom (#2 of 2) 7 8 9 2 3 5 6 1 - - 4 - - - - -

Deal top card [7] to Bessie 8 9 2 3 5 6 1 - - 4 - - 7 - -

Top card to bottom (#1 of 2) 9 2 3 5 6 8 1 - - 4 - - 7 - -

Top card to bottom (#2 of 2) 2 3 5 6 8 9 1 - - 4 - - 7 - -

Deal top card [2] to Player 1 3 5 6 8 9 1 2 - 4 - - 7 - -

Top card to bottom (#1 of 2) 5 6 8 9 3 1 2 - 4 - - 7 - -

Top card to bottom (#2 of 2) 6 8 9 3 5 1 2 - 4 - - 7 - -

Deal top card [6] to Player 2 8 9 3 5 1 2 - 4 6 - 7 - -

Top card to bottom (#1 of 2) 9 3 5 8 1 2 - 4 6 - 7 - -

Top card to bottom (#2 of 2) 3 5 8 9 1 2 - 4 6 - 7 - -

Deal top card [3] to Bessie 5 8 9 1 2 - 4 6 - 7 3 -

Top card to bottom (#1 of 2) 8 9 5 1 2 - 4 6 - 7 3 -


Top card to bottom (#2 of 2) 9 5 8 1 2 - 4 6 - 7 3 -

Deal top card [9] to Player 1 5 8 1 2 9 4 6 - 7 3 -

Top card to bottom (#1 of 2) 8 5 1 2 9 4 6 - 7 3 -

Top card to bottom (#2 of 2) 5 8 1 2 9 4 6 - 7 3 -

Deal top card [5] to Player 2 8 1 2 9 4 6 5 7 3 -

Top card to bottom (#1 of 2) 8 1 2 9 4 6 5 7 3 -

Top card to bottom (#1 of 2) 8 1 2 9 4 6 5 7 3 -

Deal top card [8] to Bessie - 1 2 9 4 6 5 7 3 8

Bessie will end up with the "good cards" that have been placed in

positions 3, 7, and 8 in the original deck.

This problem is one of data structure manipulation. The explicit example in


the directions shows everything one needs to solve the task:

 Read the parameters


 Set up a 'dummy' deck so you can see where the cards end up
 Deal out the cards according to the procedure (making special note when
Betsy's cards go by)
 Sort Betsy's positions
 Output Betsy's positions

The simplest brute force approach is simple until it comes time to "put the
top card on the bottom". One can implement this in a few ways:

 save the top card, move all the cards 'up' one slot in an array, set the
bottom card to the saved top card
 a linked list: remove the head element and place it on the end
 an oversized array that is large enough to accommodate a large number of
cards-moved-to-bottom; keep an index of the 'decktop' and 'deckbottom'.
Moving a card to the bottom just increments decktop and deckbottom while
copying the first card to the bottom.

My solution (below) uses the third method since it's pretty darn simple to
implement:

#include <stdio.h>
int cmp (int *a, int *b) { return *a - *b; }

main () {
FILE *fin = fopen ("cheat.in", "r");
FILE *fout = fopen ("cheat.out", "w");
int n, k, p, i, j;
int deck[100000 * 11], decktop, deckbottom, betsy[100000], nbetsy;
int player;
fscanf (fin, "%d %d %d", &n, &k, &p);

for (i = 0; i < k; i++) deck[i] = i;


player = decktop = 0;
deckbottom = k-1;
for (i = 0; i < k; i++) { /* k cards to be dealt */
/*printf ("deal %d to player %d\n", deck[decktop]+1, player);*/
if (player == n-1) betsy[nbetsy++] = deck[decktop]+1;
player = (player + 1) % n;
decktop++; /* that card is gone */
for (j = 0; j < p; j++)
deck[++deckbottom] = deck[decktop++]; /* card to bottom */
}
qsort(betsy, k/n, sizeof (int), cmp);
for (i = 0; i < k/n; i++) fprintf (fout, "%d\n", betsy[i]);
exit (0);
}

SILVER PROBLEMS

*****************************************************************************

Charm Bracelet [Kolstad/Cox, 2006]

Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of
course, she'd like to fill it with the best charms possible from the N (1 <= N
<= 3,402) available charms. Each charm i in the supplied list has a weight W i
(1 <= Wi <= 400), a 'desirability' factor D i (1 <= Di <= 100), and can be used
at most once. Bessie can only support a charm bracelet whose weight is no
more than M (1 <= M <= 12,880).

Given that weight limit as a constraint and a list of the charms with their
weights and desirability rating, deduce the maximum possible sum of ratings.
INPUT FORMAT:

* Line 1: Two space-separated integers: N and M

* Lines 2...N+1: Line i+1 describes charm i with two space-separated integers:
Wi and Di

SAMPLE INPUT (file charm.in):

4 6

1 4

2 6

3 12

2 7

INPUT DETAILS:

Four potential charms; maximum weight 6

OUTPUT FORMAT:

* Line 1: A single integer that is the greatest sum of charm


desirabilities that can be achieved given the weight constraints

SAMPLE OUTPUT (file charm.out):

23
OUTPUT DETAILS:

Without the second possible charm, the 4+12+7=23 is the highest value for
weight 1+2+3 <= 6

This is one of the classic "knapsack" problems: 'Items' with a 'value' and
'size' can be stuffed an integer number of times into a container of some
limited size with the goal of maximizing the value of the items inserted.

The classic solution pivots on a list of the best possible value that can be
obtained for the set of items so far seen. The array's subscript is 'size';
it's value is "the best value that can be obtained for the items so far
processed.

Initially, of course, the array's values are all zero. Adding the first
element is easy: bestvalue[itemweight] = itemvalue.

Subsequent items are processed one-by-one as follows. The item's weight and
value are (experimentally) added to each of the *existing* weight/value pairs
in the bestvalue array (including the 0/0 element). If the new weight/value
pair is better, it replaces the old weight value.

By way of example, consider the four items from the problem description:

1 4
2 6
3 12
2 7
The maximum allowed weight is 6, so 6+1 elements are needed in the 'bestvalue'
array:
0 0 0 0 0 0 0 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
The first element (weight 1, value 4) is easy to insert:
0 4 0 0 0 0 0 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
The second element (weight 2, value 6) requires two additions. For purposes of
explanation, we will first add it to the 0/0 element:
V-------V
0 4 *6* 0 0 0 0 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
and then to the weight=1 element, which currently has value 4:
V-------V
0 4 6 *10* 0 0 0 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
Important point:It is now clear that we can run into trouble if, for instance,
our weight was 1. In that case, we'd be modifying sequential elements --
elements whose new value should be based on the original 'best' matrix value
and not the newly increased values. Thus, we must either make a new (properly
copied) best matrix so modifications are made properly OR we must modify the
'best' matrix from the larger elements to smaller

The third element (weight 3, value 12) requires four additions (to weights 0,
1, 2, and 3). We will start at weight 3 and proceed 'backwards':

V-----------V
0 4 6 10 0 0 *22* <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)

V-----------V
0 4 6 10 0 *12* 22 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)

V-----------V
0 4 6 10 *16* 12 22 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
In the final case, we will overwrite a now inferior 'best value' element:
V-----------V
0 4 6 *12* 16 12 22 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)

The fourth and final element (weight 2, value 7) will require potential
augmentation of all 7 of the best values since all slots are now occupied.
Working backwards:

V-------V
0 4 6 12 16 12 22 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
No modifications since the aggregate weight is too large. Likewise:
V-------V
0 4 6 12 16 12 22 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
Regular calculations and potential modifications then commence. The 6th item
is overwritten since 16+7 > 22 (and so on):
V-------V
0 4 6 12 16 12 *23* <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)

V-------V
0 4 6 12 16 *19* 23 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
For weight 2 + 2, the new value 6+7=13 is less than the current best value of
16, so no modification occurs:
V-------V
0 4 6 12 16 19 23 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
Likewise for weight 1 + 2 no modificastion occurs since 4+7=11 < 12:
V-------V
0 4 6 12 16 19 23 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)
The final weight 0+2 has a new best value:
V-------V
0 4 *7* 12 16 19 23 <-- best value
0 1 2 3 4 5 6 <-- for this weight (subscript)

Having now processed all the input, the 'best value' array is complete. In
this case element bestvalue[6]=23 is the largest of all the values. One can
well imagine this would not be the case if, e.g., an item with weight 5 and
value 1,000 existed. That might make the largest value appear in some slot
other than the final one (i.e., if the other weights were all > 1). Thus we
scan the best value array to find the largest element, which is the highest
possible value that can be created within the size/weight constraints.

I coded this task using two arrays and inefficient copy operators:

#include <stdio.h>

#define MAX 12880


int best[MAX+1], newbest[MAX+1], nb;

main () {
FILE *fin = fopen ("charm.in", "r");
FILE *fout = fopen ("charm.out", "w");
int n, m, w, d, i, j, biggest;

fscanf (fin, "%d %d", &n, &m);


bzero (best, (m+1)*sizeof(int));
bzero (newbest, (m+1)*sizeof(int));
for (i = 0; i < n; i++) {
fscanf (fin, "%d %d", &w, &d);
for (j = 0; j <= m; j++) {
if (j != 0 && best[j] == 0 || j+w > m) continue;
nb = best[j] + d;
if (nb > newbest[j+w]) newbest[j+w] = nb;
}
bcopy (newbest, best, (m+1)*sizeof(int));
/*for (j = 0; j <= m; j++) printf("%2d ", best[j]);
printf (" -- %d %d\n", w, d); /* debug */
}
biggest = best[0];
for (j = 1; j <= m; j++)
if (best[j] > biggest) biggest = best[j];
fprintf (fout, "%d\n", biggest);
exit (0);
}

Richard Peng, who has coded tasks like this many times, has evolved a more
sophisticated solution that requires but one array (processed in reverse
order) and uses the cool '>?=' operator for replacing 'improved' elements.
Note that his loops are generally 'correct by construction' -- no need to
check for out-of-bounds indices since the loops are properly constrained. Of
course his solution is also just about as fast as we know how to solve a task
like this:

#include <cstdio>
#include <cstring>

int bes[12880], n, m, a, b, i, j;

int main () {
freopen ("charm.in", "r", stdin);
freopen ("charm.out", "w", stdout);
scanf ("%d%d", &n, &m);
memset (bes, 0, sizeof (bes));
for (i=0; i<n; i++){
scanf ("%d%d", &a, &b);
for (j=m; j>=a; j--)
bes[j]>?=bes[j-a]+b;
}
printf ("%d\n", bes[m]);
return 0;
}

Building Roads [Richard Ho, 2007]

Farmer John had just acquired several new farms! He wants to connect the farms
with roads so that he can travel from any farm to any other farm via a
sequence of roads; roads already connect some of the farms.

Each of the N (1 <= N <= 1,000) farms (conveniently numbered 1...N) is


represented by a position (X_i, Y_i) on the plane (0 <= X_i <= 1,000,000; 0 <=
Y_i <= 1,000,000). Given the preexisting M roads (1 <= M <= 1,000) as pairs
of connected farms, help Farmer John determine the smallest length of
additional roads he must build to connect all his farms.
INPUT FORMAT:

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: Two space-separated integers: X_i and Y_i

* Lines N+2..N+M+2: Two space-separated integers: i and j, indicating


that there is already a road connecting the farm i and farm j.

SAMPLE INPUT (file roads.in):

4 1

1 1

3 1

2 3

4 3

1 4

INPUT DETAILS:

Four farms at locations (1,1), (3,1), (2,3), and (4,3). Farms 1 and 4 are
connected by a road.

OUTPUT FORMAT:

* Line 1: Smallest length of additional roads required to connect all


farms, printed without rounding to two decimal places. Be sure to calculate
distances as 64-bit floating point numbers.

SAMPLE OUTPUT (file roads.out):


4.00

OUTPUT DETAILS:

Connect farms 1 and 2 with a road that is 2.00 units long, then connect farms
3 and 4 with a road that is 2.00 units long. This is the best we can do, and
gives us a total of 4.00 unit lengths.

We note that since all edges have non-negative weights, there will not be a
cycle in the final version of the graph. Thus, this problem is equivalent to
finding the minimum spanning tree in a graph where the edge weights are the
Euclidean distances (with the exception of a few whose distances are set to
zero).

Several minimum spanning tree algorithms can be use here. Since we're finding
the MST of a dense graph, the best option is probably the O(n^2) version of
the Prim algorithm:

 Start with the tree being a single vertex


 Keep a list of distances of every other vertex to the tree
 At each iteration
o Add the closest vertex to the tree
o Update the distances accordingly.

This runs in O(n^2) time, which suffices for this problem.

By the way: This problem can actually be done in O(nlogn+m) time. The idea is
basically the edges that could potentially be in the minimum spanning tree
must belong to what's known as the Delaunay triangulation, which has O(n)
edges. We can find the Delaunary triangulation in O(nlogn) time and apply a
fast version of Kruskal's algorithm for sparse graphs to get the desired
runtime.

Below is Chinese sophomore ShiMen Xu's compact solution (which might or might
not match the description above):

#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

ifstream fin ("roads.in");


struct Tpoint {
long long x, y;
};
Tpoint p[1010];
double dis[1010];
int N, M;

int us [1010];
double ans;

void init ();


int findRoot (int i);
void work ();

int main () {
FILE *f = fopen ("roads.out", "w");
init ();
work ();
fprintf (f, "%0.2lf\n", ans);
return 0;
}

int findRoot (int i) {


if (us[i] == i)
return i;
return us[i] = findRoot (us[i]);
}

void init () {
fin >> N >> M;
for (int i = 1; i <= N; i++)
fin >> p[i].x >> p[i].y;

for (int i = 0; i <= N; i++)


us[i] = i;

for (int i = 0; i < M; i++) {


int a , b, a1, b1;
fin >> a >> b;
if ((a1 = findRoot (a)) != (b1 = findRoot (b)))
us[a1] = b1;
}
}

void work () {
int root, cnt[1010], id;

root = findRoot (1);


memset (cnt, 0, sizeof (cnt));
for (int i = 0; i <= N; i++)
dis[i] = 10000000.0 * 1000000.0;
for (id = 1;; id++) {
for (int i = 1; i <= N; i++)
if (cnt[i] == 0)
if (root == findRoot (i))
cnt[i] = id;
double mindis = dis[0];
int minj = 0;

for (int i = 1; i <= N; i++)


if (cnt[i] == id)
for (int j = 2; j <= N; j++)
if (cnt[j] == 0) {
double d1 = sqrt ((p[j].x - p[i].x) * (p[j].x -
p[i].x) +
(p[j].y - p[i].y) * (p[j].y -
p[i].y));
dis[j] <? = d1;
if (dis[j] < mindis) {
mindis = dis[j];
minj = j;
}
}
if (minj == 0)
break;
int j1 = findRoot (minj);
ans += mindis;
us[j1] = root;
}
}

Mud Puddles [Jeffrey Wang, 2007]

Farmer John is leaving his house promptly at 6 AM for his daily milking of
Bessie. However, the previous evening saw a heavy rain, and the fields are
quite muddy. FJ starts at the point (0, 0) in the coordinate plane and heads
toward Bessie who is located at (X, Y) (-500 <= X <= 500; -500 <= Y <= 500).
He can see all N (1 <= N <= 10,000) puddles of mud, located at points (A_i,
B_i) (-500 <= A_i <= 500; -500 <= B_i <= 500) on the field. Each puddle
occupies only the point it is on.

Having just bought new boots, Farmer John absolutely does not want to dirty
them by stepping in a puddle, but he also wants to get to Bessie as quickly as
possible. He's already late because he had to count all the puddles. If Farmer
John can only travel parallel to the axes and turn at points with integer
coordinates, what is the shortest distance he must travel to reach Bessie and
keep his boots clean? There will always be a path without mud that Farmer John
can take to reach Bessie.

INPUT FORMAT:

* Line 1: Three space-separate integers: X, Y, and N.

* Lines 2...N+1: Line i+1 contains two space-separated integers: A_i


and B_i

SAMPLE INPUT (file mud.in):

1 2 7

0 2

-1 3

3 1

1 1

4 2

-1 1

2 2

INPUT DETAILS:

Bessie is at (1, 2). Farmer John sees 7 mud puddles, located at (0, 2); (-1,
3); (3, 1); (1, 1); (4, 2); (-1, 1) and (2, 2). Pictorially:

4 . . . . . . . .
3 . M . . . . . .

Y 2 . . M B M . M .

1 . M . M . M . .

0 . . * . . . . .

-1 . . . . . . . .

-2-1 0 1 2 3 4 5

OUTPUT FORMAT:

* Line 1: The minimum distance that Farmer John has to travel to reach

Bessie without stepping in mud.

SAMPLE OUTPUT (file mud.out):

11

OUTPUT DETAILS:

The best path for Farmer John is (0, 0); (-1, 0); (-2, 0); (-2, 1);

(-2, 2); (-2, 3); (-2, 4); (-1, 4); (0, 4); (0, 3); (1, 3); and (1,

2), finally reaching Bessie.

4 ******* . . . .

3 * M . * . . . .

Y 2 * . M B M . M .

1 * M . M . M . .

0 ***** . . . . .
-1 . . . . . . . .

-2-1 0 1 2 3 4 5

This is a classic 'Flood fill' algorithm. The idea is that one seeds a 'flood
fill' with an initial point followed by massive recursion to find the points
around that point.

Using a small 5 x 5 matrix as an example:

4 .. . . .
3 .. . . .
2 .. * . .
1 .. . . .
0 .. . . .
01 2 3 4
one can easily imagine starting at point 2,2 and then examining points around
it after marking those points with the 'distance' from the initial point:
4 . . . . .
3 . . 1 . .
2 . 1 * 1 .
1 . . 1 . .
0 . . . . .
0 1 2 3 4
and then examining points around those 1's:
4 . . 2 . .
3 . 2 1 2 .
2 2 1 * 1 2
1 . 2 1 2 .
0 . . 2 . .
0 1 2 3 4
and so on until all distances are determined:
4|4 3 2 3 4
3|3 2 1 2 3
2|2 1 * 1 2
1|3 2 1 2 3
0|4 3 2 3 4
+---------
0 1 2 3 4

Adding in obstacles just makes some of the distances a bit different since
certain cells can not be used in the recursive search. Here is the flooded
version of the sample input data:
4| 6 7 8 9 10 11 10 9
3| 5 M 9 10 11 10 9 8
Y 2| 4 5 M B M 11 M 7
1| 3 M 1 M 3 M 5 6
0| 2 1 * 1 2 3 4 5
-1| 3 2 1 2 3 4 5 6
+-----------------------
-2 -1 0 1 2 3 4 5
X
The final '11' has not been written on to the 'B' square on which Bessie sits,
but it's clear that 11 is the answer.

The obvious way to implement this algorithm is so simple (yet wrong):

check(x,y,dist) {
if (dist > matrix[x,y]) return;
matrix[x,y] = dist;
if (validsubscript (x+1, y ) check (x+1, y , dist+1);
if (validsubscript (x-1, y ) check (x-1, y , dist+1);
if (validsubscript (x , y+1) check (x , y+1, dist+1);
if (validsubscript (x , y-1) check (x , y-1, dist+1);
}
The pleasing intuitive brevity, though, is nothing but a trap. Why? Because,
as shown, the subprogram will quickly recurse to check(x+1, ...), check
(x+2, ...) and so on down the x axis instead of the geometrically nice
circular pattern exhibited a few paragraphs back. Will the algorithm still get
the right answer? Yes! Is there a way to implement the algorithm that will
take longer to get to the right answer? Probably not.

Instead, one needs to implement a FIFO queue structure so that all four of the
'next elements to search' are queued before any of them is examined. Bonus
performance for knowing if an element is already queued (and thus avoiding
requeueing it). Note that one should requeue elements whose value has changed
-- but it's hardly ever an advantage to have the same element on the queue
more than once.

Aside: queues can be nicely implemented with linked lists. Such lists are
slightly tricky to get 'right the first time' and sometimes are implemented
to allocate a tiny bit of storage for each element added to the list. In
contest programming, one might as well just make a big array and circle
through it. If you need more space than the array allows, you would have
needed more linked-list space -- and failed very late in the program's
execution. Better to expose the potential failure up front!

The final challenge in this task was the coordinate scheme: it starts at some
large negative number, so all subscripts need to be shifted into a valid
range. The first program below does this with #define's; the second explicitly
codes the shift into each subscript.
My solution is intended to be straightforward with the tiny trick of using a
bit more storage to set up a 'border' around the edges of the matrix. This
avoids having to validate every possible enqueueing to ensure the subscripts
will not go out of bounds for the array:

#include <stdio.h>

#define RANGE 500


#define FIELD(i,j) field[(i)+RANGE+2][(j)+RANGE+2]
#define DONE(i,j) done[(i)+RANGE+2][(j)+RANGE+2]
#define QUEUED(i,j) queued[(i)+RANGE+2][(j)+RANGE+2]

short field[2*RANGE+5][2*RANGE+5];
char done[2*RANGE+5][2*RANGE+5], queued[2*RANGE+5][2*RANGE+5];

struct q { int x, y; } queue[800000];


int nq = 0, head = 0; tail = 0;

tryenq (x,y,thisdist) {
if (FIELD(x,y) != 0 && thisdist >= FIELD(x,y)) return;
if (QUEUED(x,y)) return;
QUEUED(x,y) = 1;
FIELD(x,y) = thisdist;
if (++nq >= 790000) exit (9);
queue[tail].x = x;
queue[tail].y = y;
if (++tail >= 800000) tail = 0;
}

main () {
FILE *fin = fopen ("mud.in", "r");
FILE *fout = fopen ("mud.out", "w");
int X, Y, N, i, j, A, B;

fscanf (fin, "%d %d %d", &X, &Y, &N);


for (i = 0; i < N; i++) {
fscanf (fin, "%d %d", &A, &B);
DONE(A,B) = -1;
}
/* set up a border so we don't look outside box: */
for (i = -RANGE; i <= RANGE; i++)
FIELD(-RANGE-1,i) = FIELD(RANGE+1,i) = FIELD(i,RANGE+1) =
FIELD(i,-RANGE-1) = -1;
tryenq (0,0,0);
while (nq) {
int x=queue[head].x; /* dequeue */
int y=queue[head].y;
QUEUED(x,y) = 0;
nq--;
if (++head >= 800000) head = 0;

/* enqueue if needed: */
if (DONE(x,y)) continue;
DONE(x,y) = 1;
tryenq(x+1, y , FIELD(x,y)+1);
tryenq(x-1, y , FIELD(x,y)+1);
tryenq(x , y+1, FIELD(x,y)+1);
tryenq(x , y-1, FIELD(x,y)+1);
}

fprintf (fout, "%d\n", FIELD(X,Y));


exit (0);
}

Richard Peng's solution is a bit shorter (as usual). Among the techniques for
compaction:

 The 'dir' array of the four pairs of integers that describe the four
potential squares to be newly examined
 Using array subscripts rather than an structure for storing the queue
(probably a bit more obscure to understand if you look at the program
six months later)
 Omission of tagging to prevent extra queueing/checking
 Inclusion of negative elements in the 'vis' array to prevent extra
processing (probably a big win)

Richard's program is over 1.5x faster than the program above.

#include <cstdio>
#include <cstring>

short vis[1020][1020], r, c, shif, q[1100000][2];


int a, b, x, y, n, tai;
int dir[4][2]={-1, 0, 1, 0, 0, -1, 0, 1};

void add (int r1, int c1, int d) {


if (r1>=0 && r1<r && c1>=0 && c1<c && vis[r1][c1]==-1) {
vis[r1][c1]=d;
q[tai][0]=r1;
q[tai][1]=c1;
tai++;
}
}

int main () {
int i, j;
freopen ("mud.in", "r", stdin);
freopen ("mud.out", "w", stdout);
r = 1010; c = 1010; shif = 505;
tai = 0;
scanf ("%d%d%d", &x, &y, &n);
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
vis[i][j] = -1;
for (i = 0; i < n; i++){
scanf ("%d%d", &a, &b);
vis[a+shif][b+shif] = -2;
}
tai = 0;
add (shif, shif, 0);
for (i = 0; i < tai; i++)
for (j = 0; j < 4; j++)
add (q[i][0]+dir[j][0], q[i][1]+dir[j][1], vis[q[i][0]][q[i][1]]
+1);
printf ("%d\n", vis[x+shif][y+shif]);
return 0;
}

GOLD PROBLEMS

*****************************************************************************

Sightseeing Cows [Reid Barton, 2007]

Farmer John has decided to reward his cows for their hard work by taking them
on a tour of the big city! The cows must decide how best to spend their free
time.

Fortunately, they have a detailed city map showing the L (2 <= L <= 1000)
major landmarks (conveniently numbered 1.. L) and the P (2 <= P <= 5000)
unidirectional cow paths that join them. Farmer John will drive the cows to a
starting landmark of their choice, from which they will walk along the cow
paths to a series of other landmarks, ending back at their starting landmark
where Farmer John will pick them up and take them back to the farm. Because
space in the city is at a premium, the cow paths are very narrow and so travel
along each cow path is only allowed in one fixed direction.

While the cows may spend as much time as they like in the city, they do tend
to get bored easily. Visiting each new landmark is fun, but walking between
them takes time. The cows know the exact fun values F_i (1 <= F_i <= 1000) for
each landmark i.
The cows also know about the cowpaths. Cowpath i connects landmark L1_i to
L2_i (in the direction L1_i -> L2_i) and requires time T_i (1 <= T_i <= 1000)
to traverse.

In order to have the best possible day off, the cows want to maximize the
average fun value per unit time of their trip. Of course, the landmarks are
only fun the first time they are visited; the cows may pass through the
landmark more than once, but they do not perceive its fun value again.
Furthermore, Farmer John is making the cows visit at least two landmarks, so
that they get some exercise during their day off.

Help the cows find the maximum fun value per unit time that they can achieve.

INPUT FORMAT:

* Line 1: Two space-separated integers: L and P

* Lines 2..L+1: Line i+1 contains a single one integer: F_i

* Lines L+2..L+P+1: Line L+i+1 describes cow path i with three space-separated
integers: L1_i, L2_i, and T_i

SAMPLE INPUT (file sightsee.in):

5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2

OUTPUT FORMAT:

* Line 1: A single number given to two decimal places (do not perform
explicit rounding), the maximum possible average fun per unit time, or 0 if
the cows cannot plan any trip at all in accordance with the above rules.

SAMPLE OUTPUT (file sightsee.out):

6.00
OUTPUT DETAILS:

The trip 1 -> 2 -> 3 -> 5 -> 1 has a total fun value of 60 and a length of 10
units for an average fun per unit time of 6. The trip 2 -> 3 -> 5 -> 2 only
has an average fun per unit time of 30/6 = 5, and any trip involving landmark
4 has an average fun per unit time of less than 4.

This problem involves a graph in which each edge e has an associated length
L(e) and fun value F(e). Our goal is to find a directed cycle C minimizing
L(C) / F(C), where L(C) denotes the total length of all edges in C and F(C)
denotes the total fun value of all edges in C (note: the actual problem asks
us to maximize F(C) / L(C), but I've converted it to a minimization problem
since this is more common when we discuss shortest path type problems).

To solve this problem quickly, we employ a common trick: binary search on the
answer. Let us make a guess that the answer is X. By running one instance of
the Bellman-Ford shortest path algorithm (in O(LP) time), we will be able to
tell if this guess is too high or too low, thereby homing in on the correct
answer. The one feature of the Bellman-Ford algorithm we use here is the fact
that it can detect whether or not a negative-length direct cycle exists in a
graph (we won't go into how this is done here, since this is a common
algorithm).

How can negative cycle detection tell us if our guess X is too high or too
low? Well, we would like to check if the minimum value of L(C)/F(C) over all
cycles C is less than X (i.e., if there exists a cycle C such that L(C)/F(C)
<= X). If so, then our guess is too high; otherwise it is too low. But asking
whether there exists a cycle C such that L(C)/F(C) <= X is the same as asking
whether there exists a cycle C such that L(C) <= X F(C), which is the same as
asking whether there exists a cycle C such that L(C) - X F(C) <= 0. So if we
define the cost of each edge e as Z(e) = L(e) - X F(e), then this turns into a
negative cycle detection problem with respect to the Z(e)'s!

Below is Chinese Junior Danqi Chen's full-credit beautifully formatted PASCAL


solution (this is precisely as she submitted it) which might or might not
match the description above.

program sightsee;

const

finp = 'sightsee.in';

fout = 'sightsee.out';

maxn = 1000 + 5;
eps = 1e-4;

type

nodeptr = ^node;

node = record

p, len : longint;

next : nodeptr;

end;

var

hash : array [1 .. maxn] of boolean;

queue, edge : array [1 .. maxn] of longint;

dist : array [1 .. maxn] of extended;

a : array [1 .. maxn] of nodeptr;

cost : array [1 .. maxn] of longint;

n, m : longint;

procedure create(x, y, c : longint);

var

tmp : nodeptr;

begin

new(tmp); tmp ^.p := y; tmp ^. len := c;

tmp ^.next := a[x]; a[x] := tmp;

end;

procedure init;

var

i : longint;
x, y, c : longint;

begin

read(n, m);

for i := 1 to n do read(cost[i]);

for i := 1 to n do a[i] := nil;

for i := 1 to m do

begin

read(x, y, c);

create(x, y, c);

end;

end;

function nxt(i : longint): longint;

begin

if i = maxn then nxt := 1 else nxt := i + 1;

end;

function check(limit : extended): boolean;

var

h, t, i : longint;

tmp : nodeptr;

v : extended;

begin

check := true;

fillchar(hash, sizeof(hash), false);

h := 0; t := 0;

for i := 1 to n do

begin
inc(t); queue[t] := i; hash[i] := true;

dist[i] := 0; edge[i] := 0;

end;

while (h <> t) do

begin

h := nxt(h);

tmp := a[queue[h]];

while (tmp <> nil) do

begin

v := tmp ^. len * limit - cost[tmp^.p];

if (dist[queue[h]] + v < dist[tmp^.p]) then

begin

dist[tmp^.p] := dist[queue[h]] + v;

edge[tmp^.p] := edge[queue[h]] + 1;

if edge[tmp ^. p] > n then exit;

if not hash[tmp^.p] then

begin

t := nxt(t);

queue[t] := tmp^. p;

hash[tmp ^.p] := true;

end;

end;

tmp := tmp ^. next;

end;

hash[queue[h]] := false;

end;

check := false;

end;
procedure work;

var

l, r, mid : extended;

begin

l := 0; r := 1000;

while (r - l > eps) do

begin

mid := (l + r) / 2;

if check(mid) then l := mid else r := mid;

end;

writeln(l : 0 : 2);

end;

begin

assign(input, finp); reset(input);

assign(output, fout); rewrite(output);

init;

work;

close(input); close(output);

end.

Gourmet Grazers [Alex Schwendner, 2007]

Like so many others, the cows have developed very haughty tastes and will no
longer graze on just any grass. Instead, Farmer John must purchase gourmet
organic grass at the Green Grass Grocers store for each of his N (1 <= N <=
100,000) cows.

Each cow_i demands grass of price at least A_i (1 <= A_i <= 1,000,000,000) and
with a greenness score at least B_i (1 <= B_i <= 1,000,000,000). The GGG store
has M (1 <= M <= 100,000) different types of grass available, each with a
price C_i (1 <= C_i <= 1,000,000,000) and a greenness score of D_i (1 <= D_i
<= 1,000,000,000). Of course, no cow would sacrifice her individuality, so no
two cows can have the same kind of grass.

Help Farmer John satisfy the cows' expensive gourmet tastes while spending as
little money as is necessary.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and M.

* Lines 2..N+1: Line i+1 contains two space-separated integers: A_i


and B_i

* Lines N+2..N+M+1: Line i+N+1 contains two space-separated integers:


C_i and D_i

SAMPLE INPUT (file gourmet.in):

4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4

OUTPUT FORMAT:

* Line 1: A single integer which is the minimum cost to satisfy all


the cows. If that is not possible, output -1.

SAMPLE OUTPUT (file gourmet.out):

12

OUTPUT DETAILS:

Cow 1 eats grass 2 at cost 2, cow 2 eats grass 3 at cost 4, cow 3 eats grass 6
at cost 2, and cow 4 eats grass 7 at cost 4, for a total cost of 12.
The greedy solution works for this task. The first observation is if we sort
the requests and grasses by decreasing order of green-ness, the set of grass
we need to consider for each request is precisely the set of all grass that
hasn't been used yet that has a higher greenness. So we can add grasses to the
set as we 'sweep' by them and remove the grasses as we use them.

Let's just consider the prices. The claim is that at each moment, we can pick
the cheapest grass that will satisfy the cow. This is true since suppose we
pick a more expensive grass and use the cheaper one later, we can swap the
choices while keeping both cows satisfied without increasing the total cost.

Now the problem becomes a data structure problem, we need to support the
following operations: insertion, deletion, find the first element with key
bigger than a given value and we want to do each operation in O(logn) time.

This can be done using STL set. It's also possible to do this without STL
using a binary index tree by first assigning values from 1 to n to the prices,
then construct a full binary tree with the prices at leafs and track on each
node whether the subtree below has values. Both give O(nlogn) solutions.

Below is an extraordinarily compact full-credit solution submitted by


Belarus's Gennady Korotkevich:

#include <iterator>

#include <fstream>

#include <vector>

#include <algorithm>

#include <set>

#define __int64 long long

using namespace std;

vector < pair <int,int> > c,f;

set < pair <int,int> > a;

int main () {

FILE *in = fopen ("gourmet.in","r");


FILE *out = fopen ("gourmet.out","w");

int n, m, i, q, w;

fscanf (in, "%d%d", &n, &m);

for (i=0; i<n; i++) {

fscanf (in, "%d%d", &q, &w);

c.push_back (make_pair (w, q));

for (i=0; i<m; i++) {

fscanf (in, "%d%d", &q, &w);

f.push_back (make_pair (w, q));

sort (c.begin (), c.end ());

sort (f.begin (), f.end ());

int r = m - 1;

__int64 ans = 0;

a.clear ();

for (i=n-1;i>=0;i--) {

while (1) {

if (r < 0) break;

if (f[r].first >= c[i].first) {

a.insert (make_pair (f[r].second, r));

r--;

else break;

set< pair <int,int> >::iterator d =

a.lower_bound (make_pair (c[i].second, -1));


if (d == a.end ()) {

fprintf (out, "-1\n");

return 0;

ans += (*d).first;

a.erase (d);

fprintf (out, "%Ld\n", ans);

return 0;

Best Cow Line, Gold [Christos Tzamos, 2007]

FJ is about to take his N (1 <= N <= 30,000) cows to the annual "Farmer of the
Year" competition. In this contest every farmer arranges his cows in a line
and herds them past the judges.

The contest organizers adopted a new registration scheme this year: simply
register the initial letter of every cow in the order they will appear (e.g.,
If FJ takes Bessie, Sylvia, and Dora in that order, he just registers BSD).
After the registration phase ends, every group is judged in increasing
lexicographic order (i.e., alphabetical order) according to the string of the
initials of the cows' names.

FJ is very busy this year and has to hurry back to his farm, so he wants to be
judged as early as possible. He decides to rearrange his cows, who have
already lined up, before registering them.

FJ marks a location for a new line of the competing cows. He then proceeds to
marshal the cows from the old line to the new one by repeatedly sending either
the first or last cow in the (remainder of the) original line to the end of
the new line. When he's finished, FJ takes his cows for registration in this
new order.

Given the initial order of his cows, determine the least lexicographic string
of initials he can make this way.
PROBLEM NAME: bclgold

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single initial ('A'..'Z') of the


cow in the ith position in the original line

SAMPLE INPUT (file bclgold.in):

6
A
C
D
B
C
B

INPUT DETAILS:

FJ has 6 cows in this order: ACDBCB

OUTPUT FORMAT:

The least lexicographic string he can make. Every line (except perhaps the
last one) contains the initials of 80 cows ('A'..'Z') in the new line.

SAMPLE OUTPUT (file bclgold.out):

ABCBCD

OUTPUT DETAILS:

Step Original New


#1 ACDBCB
#2 CDBCB A
#3 CDBC AB
#4 CDB ABC
#5 CD ABCB
#6 D ABCBC
#7 ABCBCD

This problem can be solved with dynamic programming on the intervals of cows
but there is also a simple greedy strategy.

Between the two cows in the edges, you must always pick the cow with the
smallest initial letter. If both cows have the same initial letter in order to
decide you must look a little bit deeper and check the second cows in the
line's edges or the third ones if those are equal and so on until you find two
cows that are different. Then you pick the cow from the side of the smallest
one.

This process can be summarized as follows.

At any given interval [a,b] with string S([a,b]) you choose:

Cow a if S([a,b]) < rev( S([a,b]) )


Cow b otherwise
where rev(S) is the reverse string e.g. rev("abc") = "cba"

This can be implemented in O(N^2) but we can achieve O(NlogN) by using suffix
arrays.

Here are the two implementations:

The O(N^2)

#include<cstdio>

char S[2010],ln=0;

void prnt(char a) {
if(ln==80) {printf("\n");ln=0;}
printf("%c",a);ln++;
}

int main() {
int i,j,N,pi,pj,val;
freopen("bcl.in" ,"r",stdin );
freopen("bcl.out","w",stdout);
scanf("%d",&N);
for(i=0;i<N;i++) scanf(" %c ",S+i);
i=0,j=N-1;
while(i<=j) {
if(S[i]<S[j]) {prnt(S[i]);i++;}
else if(S[i]>S[j]) {prnt(S[j]);j--;}
else {
pi=i+1;pj=j-1;val=S[i];
while( pj-pi>1 && S[pi]==S[pj]) {pi++,pj--;}
if(S[pi]<S[pj]) prnt(S[i]),i++;
else prnt(S[j]),j--;
}
}
printf("\n");
return 0;
}
And the O(NlogN)

#include<cstdio>
#include<cstring>
#include<cstdlib>

#define MAXN 500050

char S[2*MAXN];
int N,ln=0;
int o[2][2*MAXN], t[2*MAXN][2];
int A[2*MAXN], B[2*MAXN], C[2*MAXN], D[2*MAXN];

void prnt(char a) {
if(ln==80) {printf("\n");ln=0;}
printf("%c",a);ln++;
}

int main() {

int i, j, jj, x, k;

freopen("bcl.in" ,"r",stdin );
freopen("bcl.out","w",stdout);
scanf("%d",&N);
for(i=0;i<N;i++) {
scanf(" %c ",S+i);
S[N+i] = S[i];
}

memset(A, 0, sizeof(A));
for (i = 0; i < 2*N; ++i) A[(int)(S[i]-'A')] = 1;
for (i = 1; i < 26; ++i) A[i] += A[i-1];
for (i = 0; i < 2*N; ++i) o[0][i] = A[(int)(S[i]-'A')];
x=0;
for (j = 0, jj = 1, k = 0; jj < N && k < 2*N; ++j, jj <<= 1) {

memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));

for (i = 0; i < N; ++i) {


++A[ t[i][0] = o[x][i] ];
++B[ t[i][1] = (i+jj<N) ? o[x][i+jj] : 0 ];
}

for (i = N; i < 2*N; ++i) {


++A[ t[i][0] = o[x][i] ];
++B[ t[i][1] = (i-jj>=N) ? o[x][i-jj] : 0 ];
}

for (i = 1; i <= 2*N; ++i) {


A[i] += A[i-1];
B[i] += B[i-1];
}

for (i = 2*N-1; i >= 0; --i)


C[--B[t[i][1]]] = i;

for (i = 2*N-1; i >= 0; --i)


D[--A[t[C[i]][0]]] = C[i];

x ^= 1;
o[x][D[0]] = k = 1;
for (i = 1; i < 2*N; ++i)
o[x][D[i]] = (k += (t[D[i]][0] != t[D[i-1]][0] ||
t[D[i]][1] != t[D[i-1]][1]));

}
i=0,j=N-1;
while(i<=j) {
if(S[i]<S[j]) {prnt(S[i]);i++;}
else if(S[i]>S[j]) {prnt(S[j]);j--;}
else if(o[x][i]<o[x][N+j]) {prnt(S[i]);i++;}
else {prnt(S[j]);j--;}
}
printf("\n");
return 0;
}

Elite 2007 November Competition contest


BRONZE PROBLEMS

**********************************************************************

Exploration [Jeffrey Wang, 2007]

Bessie is traveling on a road teeming with interesting landmarks. The road is


labeled just like a number line, and Bessie starts at the "origin" (x = 0). A
total of N (1 <= N <= 50,000) landmarks are located at points x_1, x_2, ...,
x_N (-100,000 <= x_i <= 100,000). Bessie wants to visit as many landmarks as
possible before sundown, which occurs in T (1 <= T <= 1,000,000,000) minutes.
She travels 1 distance unit in 1 minute.

Bessie will visit the landmarks in a particular order. Since the landmarks
closer to the origin are more important to Farmer John, she always heads for
the unvisited landmark closest to the origin. No two landmarks will be the
same distance away from the origin.

Help Bessie determine the maximum number of landmarks she can visit before the
day ends.

INPUT FORMAT:

* Line 1: Two space-separated integers: T and N

* Lines 2..N+1: Line i+1 contains a single integer that is the


location of the ith landmark: x_i

SAMPLE INPUT (file explore.in):

25 5

10

-3

-7

INPUT DETAILS:
Bessie has 25 minutes before sundown, and there are 5 landmarks located at
positions 10, -3, 8, -7, and 1.

OUTPUT FORMAT:

* Line 1: The maximum number of landmarks Bessie can visit.

SAMPLE OUTPUT (file explore.out):

OUTPUT DETAILS:

Bessie sequentially visits the landmarks at locations 1, -3, -7, and 8, after
which she has traveled a total of 24 minutes. She cannot visit the next
intended landmark at position 10, since this would extend her total travel
time to 26 minutes.

This is another 'ad hoc' problem: no generic algorithm. It was intended to be


the easy problem but ended ranked the most difficult. I expect many folks read
far more into it than was required.

This is not an optimization problem (it is not one where you find an optimal
route). The route procedure was explicit: visit the next unvisited node that
is closest to the origin. We know that in one dimension, distance is the
absolute value between two points so the distance to the origin for point Z is
just |Z|, the absolute value of Z.

Thus, the problem devolves into finding the route (sorting the absolute value
of the input data) and then simulating the traversal (i.e., visit successive
landmarks until the time runs out). The problem was unclear about whether the
time limit was < T or <= T, but the test data did not exploit this.

The only 'tricky part' is that the data was chosen such that an O(N 2) sort
would not succeed on the largest test cases. One needed to invoke a system
sort (e.g., qsort) or include a 'good' sort in the submitted program.

Below is my straightforward solution:


#include <stdio.h>

#include <stdlib.h>

abs(i) { return i < 0 ? -i:i; }

int compare_abs(int *a, int *b) {

return abs(*a) - abs(*b);

int list[50000];

main() {

FILE *fin = fopen ("explore.in", "r");

FILE *fout = fopen ("explore.out", "w");

int T, N, i, j, bessloc, nvisit, timevisit;

fscanf (fin, "%d %d", &T, &N);

for (i = 0; i < N; i++)

fscanf (fin, "%d", &list[i]);

qsort (list, N, sizeof(int), compare_abs);

/* start visiting: */

bessloc = 0;

nvisit = 0;

timevisit = 0;

for (i = 0; i < N; i++) {

timevisit += abs(list[i] - bessloc);


if (timevisit > T) break;

nvisit++;

bessloc = list[i];

fprintf (fout, "%d\n", nvisit);

exit (0);

Speed Reading [Jeffrey Wang, 2007]

All K (1 <= K <= 1,000) of the cows are participating in Farmer John's annual
reading contest. The competition consists of reading a single book with N (1
<= N <= 100,000) pages as fast as possible while understanding it.

Cow i has a reading speed S_i (1 <= S_i <= 100) pages per minute, a maximum
consecutive reading time T_i (1 <= T_i <= 100) minutes, and a minimum rest
time R_i (1 <= R_i <= 100) minutes. The cow can read at a rate of S_i pages
per minute, but only for T_i minutes at a time. After she stops reading to
rest, she must rest for R_i minutes before commencing reading again.

Determine the number of minutes (rounded up to the nearest full minute) that
it will take for each cow to read the book.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and K


* Lines 2..K+1: Line i+1 contains three space-separated integers: S_i,
T_i, and R_i

SAMPLE INPUT (file read.in):

10 3

2 4 1

6 1 5

3 3 3

INPUT DETAILS:

The book has 10 pages; 3 cows are competing. The first cow reads at a rate of
2 pages per minute, can read for at most 4 minutes at a time, and must rest
for 1 minute after reading. The second reads at a rate of 6 pages per minute,
can read for at most 1 minute at a time, and must rest 5 minutes after
reading. The last reads at a rate of 3 pages per minute, can read for at most
3 minutes at a time, and must rest for 3 minutes after reading.

OUTPUT FORMAT:

* Lines 1..K: Line i should indicate how many minutes (rounded up to


the nearest full minute) are required for cow i to read the whole book.

SAMPLE OUTPUT (file read.out):

OUTPUT DETAILS:
The first cow can read 8 pages in 4 minutes, rest for 1 minute, and read the
last 2 pages in a minute. The second reads 6 pages in a minute, rests for 5
minutes, and finishes in the next minute. The last reads 9 pages in 3 minutes,
rests for 3 minutes, and finishes in the next minute.

This is an 'ad hoc' programming problem: just 'figure it out' and make it
work. No commonly used algorithm or anything like that.

I personally read this as a sort of 'simulation' problem so I wrote the simple


solution that would simulate what's going on in a step-by-step way. I ran a
counter for the minutes and reduced the number of pages remaining by the speed
for each minute that went by (and incremented the busy counter so I'd know
when to rest). When it was time to rest, I incremented the minutes so that
resting would take place and then reset my busy counter. I think the solution
is simple -- and it surely runs quickly enough:

#include <stdio.h>

#include <stdlib.h>

main() {

FILE *fin = fopen ("read.in", "r");

FILE *fout = fopen ("read.out", "w");

int N, K, speed, timex, rest, i, t, minutes, pages, busy;

fscanf(fin, "%d %d", &N, &K);

for (i = 0; i < K; i++) {

fscanf (fin, "%d %d %d", &speed, &timex, &rest);

pages = N;

busy = 0;

for (minutes = 1; ; minutes++) {

pages -= speed;

busy++;

if (pages <= 0) break;


if (busy == timex) {

minutes += rest;

busy = 0;

fprintf (fout, "%d\n", minutes);

exit (0);

Richard Peng (and a host of others), on the other hand, created tricky (in my
opinion) formulae that would yield the answer at least somewhat directly (at
least without looping). One of these solutions is below. Unfortunately,
another coach who tried the same thing got wrong answers on some of the cases.
Half those who submitted solutions to this problem missed the final test case;
it appears at least some of them tried the trickier math procedures.

Here's Richard's compact quick solution:

#include <cstdio>

int ans, n, r, s, t;

int main() {

int ct;

freopen ("read.in", "r", stdin);

freopen ("read.out", "w", stdout);

scanf ("%d%d", &n, &ct);

while (ct--) {

scanf ("%d%d%d", &r, &s, &t);

ans = (s+t)*(n/(r*s));

if( n%(r*s)==0 && n!=0) ans -= t;

ans += ((n%(r*s))+r-1)/r;
printf("%d\n",ans);

return 0;

Avoid The Lakes [Jeffrey Wang, 2007]

Farmer John's farm was flooded in the most recent storm, a fact only
aggravated by the information that his cows are deathly afraid of water. His
insurance agency will only repay him, however, an amount depending on the size
of the largest "lake" on his farm.

The farm is represented as a rectangular grid with N (1 <= N <= 100) rows and
M (1 <= M <= 100) columns. Each cell in the grid is either dry or submerged,
and exactly K (1 <= K <= N*M) of the cells are submerged. As one would expect,
a lake has a central cell to which other cells connect by sharing a long edge
(not a corner). Any cell that shares a long edge with the central cell or
shares a long edge with any connected cell becomes a connected cell and is
part of the lake.

INPUT FORMAT:

* Line 1: Three space-separated integers: N, M, and K

* Lines 2..K+1: Line i+1 describes one submerged location with two
space separated integers that are its row and column: R and C

SAMPLE INPUT (file lake.in):

3 4 5
3 2

2 2

3 1

2 3

1 1

INPUT DETAILS:

The farm is a grid with three rows and four columns; five of the cells are
submerged. They are located in the positions (row 3, column 2); (row 2, column
2); (row 3, column 1); (row 2, column 3); (row 1, column 1):

# . . .

. # # .

# # . .

OUTPUT FORMAT:

* Line 1: The number of cells that the largest lake contains.

SAMPLE OUTPUT (file lake.out):

OUTPUT DETAILS:

The largest lake consists of the input's first four cells.


This is one of the incarnations of the absolute classic 'flood fill' problems.
The goal is to figure out which squares are 4-connected (no diagonals) to a
given square.

The solution relies on simple scanning of the 'lake' looking for water spots.
When one is found, a count is commenced for that spot and, recursively, its
neighbors (see the four invocations of 'lsize' inside 'lsize' itself). Each
spot that is scanned is marked so that scanning will not be attempted for that
spot again. Thus, the algorithm is linear in the number of squares scanned,
O(R*C).

One can implement a queue for scanning (a sort of 'breadth-first' approach) or


use simple recursion as the solution below indicates. Simple recursion works
because the 'marking' occurs before any of the recursive calls, each of which
is conditional on checking the 'marking'.

The solution here is clever in that it creates a buffer zone of 'marked'


(i.e., 0-valued) squares around the input matrix. Thus no range- or bounds-
checking is required to ensure that the test for 4-connectedness stays in the
legal range.

Here is coach Dr. Brian Dean's solution:

#include <stdio.h>

#include <stdlib.h>

#define MAX(a,b) ((a) > (b) ? (a) : (b))

#define MAX_N 100

int N, M, K, map[MAX_N+2][MAX_N+2];

int lsize(int i, int j) {

int a = 1; /* this square gets single count */

map[i][j] = 0;

if (map[i][j-1]) a += lsize(i,j-1);

if (map[i][j+1]) a += lsize(i,j+1);

if (map[i-1][j]) a += lsize(i-1,j);

if (map[i+1][j]) a += lsize(i+1,j);

return a;
}

int main(void) {

FILE *fp;

int i, j, k, best=0;

fp = fopen ("lake.in", "r");

fscanf (fp, "%d %d %d", &N, &M, &K);

for (k=0; k<K; k++) {

fscanf (fp, "%d %d", &i, &j);

map[i][j] = 1;

fclose (fp);

for (i=1; i<=N; i++)

for (j=1; j<=M; j++)

if (map[i][j])

best = MAX (best, lsize(i,j));

fp = fopen ("lake.out", "w");

fprintf (fp, "%d\n", best);

fclose (fp);

return 0;

SILVER PROBLEMS
*****************************************************************************

Cow Hurdles [Neal Wu, 2007]

Farmer John wants the cows to prepare for the county jumping competition, so
Bessie and the gang are practicing jumping over hurdles. They are getting
tired, though, so they want to be able to use as little energy as possible to
jump over the hurdles.

Obviously, it is not very difficult for a cow to jump over several very short
hurdles, but one tall hurdle can be very stressful. Thus, the cows are only
concerned about the height of the tallest hurdle they have to jump over.

The cows' practice room has N (1 <= N <= 300) stations, conveniently labeled
1..N. A set of M (1 <= M <= 25,000) one-way paths connects pairs of stations;
the paths are also conveniently labeled 1..M. Path i travels from station S_i
to station E_i and contains exactly one hurdle of height H_i (1 <= H_i <=
1,000,000). Cows must jump hurdles in any path they traverse.

The cows have T (1 <= T <= 40,000) tasks to complete. Task i comprises two
distinct numbers, A_i and B_i (1 <= A_i <= N; 1 <= B_i <= N), which connote
that a cow has to travel from station A_i to station B_i (by traversing over
one or more paths over some route). The cows want to take a path the minimizes
the height of the tallest hurdle they jump over when traveling from A_i to
B_i. Your job is to write a program that determines the path whose tallest
hurdle is smallest and report that height.

INPUT FORMAT:

* Line 1: Three space-separated integers: N, M, and T

* Lines 2..M+1: Line i+1 contains three space-separated integers: S_i,


E_i, and H_i
* Lines M+2..M+T+1: Line i+M+1 contains two space-separated integers
that describe task i: A_i and B_i

SAMPLE INPUT (file hurdles.in):

5 6 3

1 2 12

3 2 8

1 3 5

2 5 3

3 4 4

2 4 8

3 4

1 2

5 1

OUTPUT FORMAT:

* Lines 1..T: Line i contains the result for task i and tells the
smallest possible maximum height necessary to travel between the stations.
Output -1 if it is impossible to travel between the two stations.

SAMPLE OUTPUT (file hurdles.out):

-1
OUTPUT DETAILS:

Query #1: The best way is to simply travel on the path from station 3 to

station 4.

Query #2: There is a path from station 1 to station 2, but a better way

would be to travel from station 1 to station 3 and then to station 2.

Query #3: There are no paths that start at station 5, so it is clear that

there is no way to reach station 1 from station 5.

First of all, it is clear that this problem can be converted into a (directed)
graph, and for each of the T queries, we wish to find the shortest path
between two nodes A and B.

One possible solution is for every query, use either a single-source shortest
path algorithm (such as Dijkstra) or do a depth-first search to find the
shortest path. However, this can take up to O(N 2) time for each query, and
would then have a total running time of O(N 2 T), which is too large for this
problem's constraints.

Thus we instead want to find a way to precompute all of the shortest paths
beforehand. We do this by initializing all distances between two nodes A and B
to the cost of the edge between A and B, or infinity if no such edge exists.
Then we run the standard Floyd-Warshall algorithm (more info can be found in
the Training pages or here) to compute the shortest paths, with one
difference: If cost (a, b, c,...) represents the cost of traveling from a to b
and then from b to c, etc., then instead of

cost (i, j, k) = cost (i, j) + cost (j, k)

we now have

cost (i, j, k) = max (cost (i, j), cost (j, k)).

(The proof that this method does correctly find the shortest path is left to
the reader.)

Another possibility is to compute the all-pairs shortest path beforehand with


a different method, such as doing Dijkstra from each node. However, this is
still O(N3) and has a slightly higher constant factor.
After computing the all-pairs shortest paths, we then input each query and
output the result (in constant time for each query). Note that if the distance
between A and B is still infinity after running the shortest path algorithm,
it means that no path exists from A to B, so we output -1.

Our total running time is thus O(N 3 + T), since the Floyd-Warshall takes O(N 3)
time to compute the shortest paths, and each query takes O(1) time.

The following is a solution using this idea:

#include <cstdio>

#include <cstring>

using namespace std;

FILE *fout = fopen ("hurdles.out", "w");

FILE *fin = fopen ("hurdles.in", "r");

const int INF = 1000000000;

const int MAXN = 505;

int N, M, T;

int dist [MAXN][MAXN];

inline void minimize (int &a, int b) { if (b < a) a = b; }

int main () {

// initialize to 'infinity'

memset (dist, 63, sizeof (dist));

fscanf (fin, "%d %d %d", &N, &M, &T);

int a, b, c;
// input data

for (int i = 0; i < M; i++) {

fscanf (fin, "%d %d %d", &a, &b, &c);

a--, b--; // use 0-based indexing

dist [a][b] <?= c;

// compute the shortest paths using Floyd-Warshall

for (int k = 0; k < N; k++)

for (int i = 0; i < N; i++)

if (dist [i][k] < INF)

for (int j = 0; j < N; j++)

minimize (dist [i][j], dist [i][k] >? dist [k][j]);

// output results

for (int i = 0; i < T; i++) {

fscanf (fin, "%d %d", &a, &b);

a--, b--;

fprintf (fout, "%d\n", dist [a][b] < INF ? dist [a][b] : -1);

return 0;

Milking Time [Jeffrey Wang, 2007]


Bessie is such a hard-working cow. In fact, she is so focused on maximizing
her productivity that she decides to schedule her next N (1 <= N <= 1,000,000)
hours (conveniently labeled 0..N-1) so that she produces as much milk as
possible.

Farmer John has a list of M (1 <= M <= 1,000) possibly overlapping intervals
in which he is available for milking. Each interval i has a starting hour (0
<= starting_hour_i < N), an ending hour (starting_hour_i < ending_hour_i <=
N), and a corresponding efficiency (1 <= efficiency_i <= 1,000,000) which
indicates how many gallons of milk that he can get out of Bessie in that
interval. Farmer John starts and stops milking at the beginning of the
starting hour and ending hour, respectively. When being milked, Bessie must be
milked through an entire interval.

Even Bessie has her limitations, though. After being milked during any
interval, she must rest R (1 <= R <= N) hours before she can start milking
again. Given Farmer Johns list of intervals, determine the maximum amount of
milk that Bessie can produce in the N hours.

INPUT FORMAT:

* Line 1: Three space-separated integers: N, M, and R

* Lines 2..M+1: Line i+1 describes FJ's ith milking interval with
three space-separated integers: starting_hour_i, ending_hour_i, and
efficiency_i

SAMPLE INPUT (file milkprod.in):

12 4 2

1 2 8

10 12 19

3 6 24

7 10 31
INPUT DETAILS:

Bessie wants to schedule the next 12 hours; Farmer John has four intervals in
which he can milk her; Bessie must rest 2 hours after every milking. The first
interval lasts from hour 1 to hour 2, the second from hour 10 to hour 12, the
third from hour 3 to hour 6, and the fourth from hour 7 to hour 10. Farmer
John can get 8, 19, 24, and 31 gallons of milk, respectively, from Bessie in
those intervals.

OUTPUT FORMAT:

* Line 1: The maximum number of gallons of milk that Bessie can

product in the N hours

SAMPLE OUTPUT (file milkprod.out):

43

OUTPUT DETAILS:

If Bessie uses the first interval, she cannot use the third because she needs
2 hours of rest. If she uses the second, she cannot use the fourth. Lastly,
if she uses the third, she cannot use the fourth. The best situation is
choosing the second and third intervals, producing 43 gallons of milk.

The goal of this problem is to select a disjoint set of intervals having


maximum total efficiency. The technical term for such a problem would be to
find a maximum-efficiency "packing" of intervals. If the intervals all have
the same efficiency (i.e., if we simply want to select a maximum number of
disjoint intervals), then this is a rather well-known problem with a simple
greedy solution: repeatedly choose the interval ending earliest, remove all
the intervals it overlaps from consideration, and repeat. Since our problem is
a more complicated "weighted" version of this problem, however, we can no
longer use a simple greedy approach, and we need to use dynamic programming
instead.
We begin by sorting the intervals according to their ending times. Let E(j)
denote the maximum efficiency we can obtain by a disjoint collection of just
intervals i...j. We will compute E(1), E(2), ..., E(n) in order. When it comes
time to compute E(j), this will be easy since we will have already computed
E(1) ... E(j-1). Here is the formula:

E(j) = max(E(j-1), j.efficiency + max{E(i) : i

<="j.start})" i.end and> What does this mean? Well, the optimal solution for
intervals 1...j either includes interval j or it doesn't. To cover both cases,
we take the best of two solutions: the best solution for intervals 1...j that
_doesn't_ contain j, and the best solution for intervals 1...j that _does_
contain j. In the first case, the optimal solution value is just E(j-1), since
we only get to use intervals 1...j-1. In the second case, we get to count the
efficiency of interval j towards our total value, and then we finish off our
solution by adding in E(i) for the "best" preceding interval i (where we only
consider those intervals i ending before j starts).

A straightforward application of the formula above to compute E(1), E(2), ...,


E(n) gives us an O(n^2) running time, which is fine for this problem. With a
bit of extra cleverness, we can actually get the running time down to O(n log
n).

If you would like to test whether or not you understand the principle behind
this solution well, consider the following related problem: you are given n
intervals that collectively cover the range 0....1,000,000, where each
interval has an associated cost. Your goal is to find a minimum-cost subset of
the intervals that still covers the range 0....1,000,000. Target running time:
O(n^2), or O(n log n) if you are extra clever.

Here is an O(n^2) solution to the milking time problem by Brian Dean:

#include <stdio.h>

#include <stdio.h>

#define MAX_M 1000

typedef struct {

int start;

int end;

int efficiency;

} Interval;
Interval I[MAX_M];

int N, M, K, Best[MAX_M];

static int Icomp(const void *p1, const void *p2)

Interval *I1 = (Interval *)p1;

Interval *I2 = (Interval *)p2;

return I1->end - I2->end;

int main(void)

int i, j, best=-1;

FILE *fp;

fp = fopen ("milkprod.in", "r");

fscanf (fp, "%d %d %d", &N, &M, &K);

for (i=0; i<M; i++)

fscanf (fp, "%d %d %d", &I[i].start, &I[i].end, &I[i].efficiency);

fclose (fp);

qsort (I, M, sizeof(Interval), Icomp);

for (j=0; j<M; j++) {

Best[j] = I[j].efficiency;

for (i=0; i<j; i++)

if (I[i].end + K <= I[j].start && Best[i] + I[j].efficiency > Best[j])

Best[j] = Best[i] + I[j].efficiency;

if (Best[j] > best) best = Best[j];


}

fp = fopen ("milkprod.out", "w");

fprintf (fp ,"%d\n", best);

fclose (fp);

Best Cow Line [Christos Tzamos, 2007]

FJ is about to take his N (1 <= N <= 2,000) cows to the annual "Farmer of the
Year" competition. In this contest every farmer arranges his cows in a line
and herds them past the judges.

The contest organizers adopted a new registration scheme this year: simply
register the initial letter of every cow in the order they will appear (i.e.,
If FJ takes Bessie, Sylvia, and Dora in that order he just registers BSD).
After the registration phase ends, every group is judged in increasing
lexicographic order according to the string of the initials of the cows'
names.

FJ is very busy this year and has to hurry back to his farm, so he wants to be
judged as early as possible. He decides to rearrange his cows, who have
already lined up, before registering them.

FJ marks a location for a new line of the competing cows. He then proceeds to
marshal the cows from the old line to the new one by repeatedly sending either
the first or last cow in the (remainder of the) original line to the end of
the new line. When he's finished, FJ takes his cows for registration in this
new order.

Given the initial order of his cows, determine the least lexicographic string
of initials he can make this way.
PROBLEM NAME: bcl

INPUT FORMAT:

* Line 1: A single integer: N

* Lines 2..N+1: Line i+1 contains a single initial ('A'..'Z') of the


cow in the ith position in the original line

SAMPLE INPUT (file bcl.in):

INPUT DETAILS:

FJ has 6 cows in this order: ACDBCB

OUTPUT FORMAT:

The least lexicographic string he can make. Every line (except perhaps the
last one) contains the initials of 80 cows ('A'..'Z') in the new line.

SAMPLE OUTPUT (file bcl.out):


ABCBCD

OUTPUT DETAILS:

Step Original New

#1 ACDBCB

#2 CDBCB A

#3 CDBC AB

#4 CDB ABC

#5 CD ABCB

#6 D ABCBC

#7 ABCBCD

This problem can be solved with dynamic programming on the intervals of cows
but there is also a simple greedy strategy.

Between the two cows in the edges, you must always pick the cow with the
smallest initial letter. If both cows have the same initial letter in order to
decide you must look a little bit deeper and check the second cows in the
line's edges or the third ones if those are equal and so on until you find two
cows that are different. Then you pick the cow from the side of the smallest
one.

This process can be summarized as follows.

At any given interval [a,b] with string S([a,b]) you choose:

Cow a if S([a,b]) < rev( S([a,b]) )


Cow b otherwise
where rev(S) is the reverse string e.g. rev("abc") = "cba"

This can be implemented in O(N^2) but we can achieve O(NlogN) by using suffix
arrays.

Here are the two implementations:


The O(N^2)
#include<cstdio>

char S[2010],ln=0;

void prnt(char a) {
if(ln==80) {printf("\n");ln=0;}
printf("%c",a);ln++;
}

int main() {
int i,j,N,pi,pj,val;
freopen("bcl.in" ,"r",stdin );
freopen("bcl.out","w",stdout);
scanf("%d",&N);
for(i=0;i<N;i++) scanf(" %c ",S+i);
i=0,j=N-1;
while(i<=j) {
if(S[i]<S[j]) {prnt(S[i]);i++;}
else if(S[i]>S[j]) {prnt(S[j]);j--;}
else {
pi=i+1;pj=j-1;val=S[i];
while( pj-pi>1 && S[pi]==S[pj]) {pi++,pj--;}
if(S[pi]<S[pj]) prnt(S[i]),i++;
else prnt(S[j]),j--;
}
}
printf("\n");
return 0;
}

And the O(NlogN)

#include<cstdio>
#include<cstring>
#include<cstdlib>

#define MAXN 500050

char S[2*MAXN];
int N,ln=0;
int o[2][2*MAXN], t[2*MAXN][2];
int A[2*MAXN], B[2*MAXN], C[2*MAXN], D[2*MAXN];

void prnt(char a) {
if(ln==80) {printf("\n");ln=0;}
printf("%c",a);ln++;
}
int main() {

int i, j, jj, x, k;

freopen("bcl.in" ,"r",stdin );
freopen("bcl.out","w",stdout);
scanf("%d",&N);
for(i=0;i<N;i++) {
scanf(" %c ",S+i);
S[N+i] = S[i];
}

memset(A, 0, sizeof(A));
for (i = 0; i < 2*N; ++i) A[(int)(S[i]-'A')] = 1;
for (i = 1; i < 26; ++i) A[i] += A[i-1];
for (i = 0; i < 2*N; ++i) o[0][i] = A[(int)(S[i]-'A')];
x=0;
for (j = 0, jj = 1, k = 0; jj < N && k < 2*N; ++j, jj <<= 1) {

memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));

for (i = 0; i < N; ++i) {


++A[ t[i][0] = o[x][i] ];
++B[ t[i][1] = (i+jj<N) ? o[x][i+jj] : 0 ];
}

for (i = N; i < 2*N; ++i) {


++A[ t[i][0] = o[x][i] ];
++B[ t[i][1] = (i-jj>=N) ? o[x][i-jj] : 0 ];
}

for (i = 1; i <= 2*N; ++i) {


A[i] += A[i-1];
B[i] += B[i-1];
}

for (i = 2*N-1; i >= 0; --i)


C[--B[t[i][1]]] = i;

for (i = 2*N-1; i >= 0; --i)


D[--A[t[C[i]][0]]] = C[i];

x ^= 1;
o[x][D[0]] = k = 1;
for (i = 1; i < 2*N; ++i)
o[x][D[i]] = (k += (t[D[i]][0] != t[D[i-1]][0] ||
t[D[i]][1] != t[D[i-1]][1]));
}
i=0,j=N-1;
while(i<=j) {
if(S[i]<S[j]) {prnt(S[i]);i++;}
else if(S[i]>S[j]) {prnt(S[j]);j--;}
else if(o[x][i]<o[x][N+j]) {prnt(S[i]);i++;}
else {prnt(S[j]);j--;}
}
printf("\n");
return 0;
}

GOLD PROBLEMS

*****************************************************************************

Telephone Wire [Jeffrey Wang, 2007]

Farmer John's cows are getting restless about their poor telephone service;
they want FJ to replace the old telephone wire with new, more efficient wire.
The new wiring will utilize N (2 <= N <= 100,000) already-installed telephone
poles, each with some height_i meters (1 <= height_i <= 100). The new wire
will connect the tops of each pair of adjacent poles and will incur a penalty
cost C * the two poles' height difference for each section of wire where the
poles are of different heights (1 <= C <= 100). The poles, of course, are in a
certain sequence and can not be moved. Farmer John figures that if he makes
some poles taller he can reduce his penalties, though with some other
additional cost. He can add an integer X number of meters to a pole at a cost
of X^2.

Help Farmer John determine the cheapest combination of growing pole heights
and connecting wire so that the cows can get their new and improved service.

INPUT FORMAT:

* Line 1: Two space-separated integers: N and C

* Lines 2..N+1: Line i+1 contains a single integer: height_i


SAMPLE INPUT (file telewire.in):

5 2
2
3
5
1
4

INPUT DETAILS:

There are 5 telephone poles, and the vertical distance penalty is $2/meter.
The poles initially have heights of 2, 3, 5, 1, and 4, respectively.

OUTPUT FORMAT:

* Line 1: The minimum total amount of money that it will cost Farmer
John to attach the new telephone wire.

SAMPLE OUTPUT (file telewire.out):

15

OUTPUT DETAILS:

The best way is for Farmer John to raise the first pole by 1 unit and the
fourth pole by 2 units, making the heights (in order) 3, 3, 5, 3, and 4. This
costs $5. The remaining wiring will cost $2*(0+2+2+1) = $10, for a
total of $15.

Let H[i] be the original height of the i-th pole, and let f(n, h) be the
minimum cost for n poles with the n-th pole having height h. Then:

f(n, h) = min { (H[i]-h)^2 + f(n-1, h') + C|h'-h| } for all h'

With a straightforward dynamic programming implementation, this runs in


O(N*H2), where H is the maximum height. However, by splitting up the
recurrence relation into two cases, one where h' >= h and one where h' < h, we
can rewrite it as:

f(n, h) = (H[i]-h)^2 + min { -C*h + min { f(n-1, h')+C*h' } (for h' >= h),

C*h + min { f(n-1, h')-C*h' } (for h' < h) }

Define low(n, h) := min over h' >= h { f(n, h')+C*h' }


and high(n, h) := min over h' < h { f(n, h')-C*h' }

Then f(n, h) = (H[i]-h)^2 + min { -C*h+low(n-1, h), C*h+high(n-1, h) }

low(n, h) and high(n, h) for all n, h can be computed in O(N*H) time; thus
f(n, h) can be computed in O(N*H) time as well. A final implementation detail:
an array of size O(N*H) exceeds the the memory limit, but only two "rows" of
the DP table are needed at a time, so an array of size 2*H is sufficient.

Below is Richard Peng's solution:

#include <cstdio>

#define MAXN 110000

#define MAXH 101

int h[MAXN], bes[2][MAXH], ans, huge, bes1, c, n;

inline int sqr (int x){return x*x; }

int main (){

int i, j, pre, cur;

freopen ("telewire.in", "r", stdin);

freopen ("telewire.out", "w", stdout);

huge = 2100000000;

scanf ("%d%d", &n, &c);

for (i = 0; i<n; i++) scanf ("%d\n", &h[i]);

for (i = 0; i<MAXH; i++)

bes[0][i] = (i> = h[0]) ? sqr(h[0]-i) : huge;

for (i = 1; i<n; i++){

pre = (i+1)%2;

cur = i%2;
for (bes1 = huge, j = 0; j<MAXH; j++){

bes1 <?= bes[pre][j]-j*c;

bes[cur][j] = bes1+j*c;

for (bes1 = huge, j = MAXH-1; j> = 0; j--){

bes1 <?= bes[pre][j]+j*c;

bes[cur][j] <?= bes1-j*c;

for (j = 0; j<MAXH; j++)

bes[cur][j] = (j> = h[i])? (bes[cur][j] + sqr(j-h[i])) : huge;

ans = huge;

for (i = 0; i<MAXH; i++) ans<? = bes[cur][i];

printf ("%d\n", ans);

return 0;

Cow Relays [Erik Bernhardsson, 2003]

For their physical fitness program, N (2 <= N <= 1,000,000) cows have decided
to run a relay race using the T (2 <= T <= 100) cow trails throughout the
pasture.

Each trail connects two different intersections (1 <= I1_i <= 1,000; 1 <= I2_i
<= 1,000), each of which is the termination for at least two trails. The cows
know the length_i of each trail (1 <= length_i <= 1,000), the two
intersections the trail connects, and they know that no two intersections are
directly connected by two different trails. The trails form a structure known
mathematically as a graph.

To run the relay, the N cows position themselves at various intersections


(some intersections might have more than one cow). They must position
themselves properly so that they can hand off the baton cow-by-cow and end up
at the proper finishing place.
Write a program to help position the cows. Find the shortest path that
connects the starting intersection (S) and the ending intersection (E) and
traverses exactly N cow trails.

INPUT FORMAT:

* Line 1: Four space-separated integers: N, T, S, and E

* Lines 2..T+1: Line i+1 describes trail i with three space-separated


integers: length_i, I1_i, and I2_i

SAMPLE INPUT (file relays.in):

2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9

OUTPUT FORMAT:

* Line 1: A single integer that is the shortest distance from


intersection S to intersection E that traverses exactly N cow trails.

SAMPLE OUTPUT (file relays.out):

10

First, note that there cannot be more than T distinct nodes in our graph,
because there are exactly T edges in the graph, and each node is an endpoint
for at least two edges.

The simplest solution that is reasonably fast is to let s[L][V] be the


shortest path from node S to node V that has length L. We can compute the
values in this array by iterating N times, each time trying to travel through
one edge from each node. The memory for this can be reduced by using a sliding
window (since computing the values for length L only uses the values for
length L - 1), and this solution uses O(N T2) time. To obtain a faster
solution, we do the following.

Assume we have the shortest path, from S to E, of length N. Then we can break
up this path into smaller paths whose lengths are powers of two. Thus, we can
compute, for each power of two that is no greater than N, the shortest path
between every pair of nodes that has a length of that power of two. This can
be done using a method similar to Floyd-Warshall in O(T 3 log N) time. (See the
code below for more details.)

After we compute the shortest paths mentioned above, we can compute shortest
paths, of length N, from S to every other node. We do this by breaking N up
into its binary representation, and for each power of two that occurs, we
compute shortest paths after adding in paths of length equal to this power.
This can be done in O(T2 log N) time. (Again, see the code below for more
details.) Thus, our overall runtime is O(T 3 log N).

#include <cstdio>

#include <cstring>

using namespace std;

FILE *fout = fopen ("relays.out", "w");

FILE *fin = fopen ("relays.in", "r");

const int INF = 1000000000;

const int MAXV = 105;

const int MAXI = 1005;

const int MAXL = 20;

int N, V, T, S, E;

// compress nodes to smaller values

int change [MAXI];

// shortest path between two nodes with a length of a power of two

int dist [MAXL][MAXV][MAXV];

// best path from S to a node

int best [MAXV], best2 [MAXV];


// change a node to a 'compressed' value

inline void check (int &ind)

if (change [ind] == -1)

change [ind] = V++;

ind = change [ind];

int main () {

// initialize arrays

memset (change, -1, sizeof (change));

memset (dist, 63, sizeof (dist));

memset (best, 63, sizeof (best));

fscanf (fin, "%d %d %d %d", &N, &T, &S, &E);

check (S);

check (E);

for (int i = 0; i < T; i++) {

int A, B, L;

fscanf (fin, "%d %d %d", &L, &A, &B);

check (A);

check (B);
// edges are paths of length 1

dist [0][A][B] <?= L;

dist [0][B][A] <?= L;

// compute shortest paths whose lengths are powers of two

// a path of length 2^p can be made by two paths of length 2^(p - 1)

for (int p = 1; (1 << p) <= N; p++)

for (int i = 0; i < V; i++)

for (int j = 0; j < V; j++)

if (dist [p - 1][i][j] < INF)

for (int k = 0; k < V; k++)

if (dist [p - 1][i][j] + dist [p - 1][j][k] < dist [p]


[i][k])

dist [p][i][k] = dist [p - 1][i][j] + dist [p - 1]


[j][k];

// combine results of each power of two in the binary representation of N

best [S] = 0;

for (int p = 0; (1 << p) <= N; p++)

if (N & (1 << p)) {

// use a temporary array 'best2' to hold the new values, and copy them to the
old array afterward

memset (best2, 63, sizeof (best2));

for (int i = 0; i < V; i++)


if (best [i] < INF)

for (int j = 0; j < V; j++)

if (best [i] + dist [p][i][j] < best2 [j])

best2 [j] = best [i] + dist [p][i][j];

memcpy (best, best2, sizeof (best2));

// best [E] is now the shortest path from S to E using N edges

fprintf (fout, "%d\n", best [E]);

return 0;

Sunscreen [Russ Cox, 2001]

To avoid unsightly burns while tanning, each of the C (1 <= C <= 2500) cows
must cover her hide with sunscreen when they're at the beach. Cow i has a
minimum and maximum SPF rating (1 <= minSPF_i <= 1,000; minSPF_i <= maxSPF_i
<= 1,000) that will work. If the SPF rating is too low, the cow suffers
sunburn; if the SPF rating is too high, the cow doesn't tan at all.

The cows have a picnic basket with L (1 <= L <= 2500) bottles of sunscreen
lotion, each bottle i with an SPF rating SPF_i (1 <= SPF_i <= 1,000). Lotion
bottle i can cover cover_i cows with lotion. A cow may lotion from only one
bottle.

What is the maximum number of cows that can protect themselves while tanning
given the available lotions?

PROBLEM NAME: tanning

INPUT FORMAT:

* Line 1: Two space-separated integers: C and L


* Lines 2..C+1: Line i describes cow i's lotion requires with two
integers: minSPF_i and maxSPF_i

* Lines C+2..C+L+1: Line i+C+1 describes a sunscreen lotion bottle I


with space-separated integers: SPF_i and cover_i

SAMPLE INPUT (file tanning.in):

3 2
3 10
2 5
1 5
6 2
4 1

INPUT DETAILS:

3 cows; 2 lotions. Cows want SPF ratings of 3..10, 2..5, and 1..5. Lotions
available: 6 (for two cows), 4 (for 1 cow). Cow 1 can use the SPF 6 lotion.
Either cow 2 or cow 3 can use the SPF 4 lotion. Only 2 cows can be covered.

OUTPUT FORMAT:

A single line with an integer that is the maximum number of cows that
can be protected while tanning

SAMPLE OUTPUT (file tanning.out):

This problem is solvable by a simple greedy algorithm: consider the bottles of


sunscreen in increasing order of SPF, and assign each one (if possible) to the
cow having the lowest maxSPF rating.

Why does this give an optimal solution? Let B denote a bottle of sunscreen
with the lowest SPF rating. If no cow is compatible with B, then clearly B
cannot be assigned in any solution, so we can ignore B. Otherwise, let C be
the cow having lowest maxSPF rating that is compatible with B. We claim that
there is always an optimal solution in which C is paired with B, so it is
"safe" to make this assignment as our algorithm progresses (i.e., it will
never make a wrong decision and end up in a situation where an optimal
solution is no longer reachable). To see this, suppose there is an optimal
solution S where C is _not_ paired with B, and consider a few cases:

(i) C and B are both unassigned in S. This case cannot happen, since we could
assign C with B and obtain an even better solution, contradicting the
optimality of S.
(ii) C is assigned in S but B is not. Here, by reassigning C to B, we obtain
an equally-good solution in which C and B are assigned.

(iii) B is assigned in S but C is not. Same as (ii), only we reassign B.

(iv) C and B are both assigned in S. Let B' be the bottle assigned to C, and
C' be the cow assigned to B. Here, you can check that it is valid to reassign
C with B and C' with B', giving us an equally good assignment in which C and B
are assigned.

Hence, an optimal solution always exists in which C and B are paired, so it is


safe to match them together.

An alternate, symmetric, solution to this problem is the following: process


the cows in increasing order of maxSPF, and for each cow C in sequence, assign
C to the minimum SPF bottle compatible with C. The analysis of this approach
follows essentially the same reasoning as above.

In terms of running time, one can implement either of the two algorithms above
in O(n log n) time. One way to do this is the following (in the case of the
first algorithm above): We first sort the bottles by SPF rating and the cows
by minSPF rating. We then scan the bottles in order and maintain a min-heap on
the cows (keyed on maxSPF) with minSPF lower than the SPF of our current
bottle. For each bottle B in order, we match it with the minimum cow from the
heap (after first removing any cows from the heap having maxSPF less than the
SPF of B).

Here is a sample C++ solution written by Richard Peng:

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <algorithm>

#include <queue>

using namespace std;

#define MAXN 20000

int n,m,ans;

pair<int,int> cow[MAXN],lotion[MAXN];
priority_queue<int> q;

void process(){

int i,i1;

while(!q.empty()) q.pop();

sort(cow,cow+n);

sort(lotion,lotion+m);

for(ans=i=i1=0;i<m;i++){

while((i1<n)&&(cow[i1].first<=lotion[i].first))

q.push(-cow[i1++].second);

while((!q.empty())&&(-(q.top())<lotion[i].first))

q.pop();

while((!q.empty())&&(lotion[i].second--)){

ans++;

q.pop();

int main(){

int i,j;

freopen("tanning.in","r",stdin);

freopen("tanning.out","w",stdout);

scanf("%d%d",&n,&m);

for(i=0;i<n;i++)

scanf("%d%d",&cow[i].first,&cow[i].second);
for(i=0;i<m;i++)

scanf("%d%d",&lotion[i].first,&lotion[i].second);

ans=0;

process();

printf("%d\n",ans);

return 0;

You might also like