APIO 2017 - Land of the Rainbow Gold

Author: Andi Qu

TL;DR

Euler's formula + a suitable data structure for 2D range queries.

Intuition

In this problem, we're asked to count the number of contiguous areas of cells on several flat rectangles. Such areas are separated by river segments and rectangle boundaries.

Where else do we count the number of areas on a flat surface?

That's right - we use Euler's formula to count the number of faces of a planar graph. This suggests that we should turn our rectangles into planar graphs.

Making the Planar Graph

We can turn a rectangle into a planar graph as so:

  • Put temporary river segments outside the border of the rectangle.
  • For each river segment, we insert its 4 corners into a set of nodes and its 4 sides into a set of edges.

Notice how the resulting graph is planar, so we can apply Euler's formula.

Applying Euler's Formula

For a planar graph, Euler's formula is given as , where is the number of faces (including the background face), is the number of edges, is the number of vertices, and is the number of connected components.

Notice how in our planar graph is equal to , where is the number of river segments and is the answer to the query. This means we must subtract from to get .

Since the whole river is a big connected component, we can just check whether the river touches the bounding rectangle to determine .

Finding , , and is a lot more complicated though.

Finding , , and

To find , , and , we can use a data structure that can handle 2D range queries efficiently.

However, the coordinates of the grid can get very large, so a simple 2D BIT or segment tree won't work here.

To work around this, we can either use a 2D BIT with coordinate compression or a persistent segment tree. See the sections on offline 2D sum queries or persistent segment trees for more details.

Code

With a persistent segment tree.

Time:

Memory:

1#include "rainbow.h"
2#include <bits/stdc++.h>
3#define FOR(i, x, y) for (int i = x; i < y; i++)
4using namespace std;
5
6const int MAXN = 2e5, MAXSEG = (6e5 + 9) * 19 + 1;
7
8int cnt = 1, segtree[MAXSEG], left_c[MAXSEG], right_c[MAXSEG];
9
10struct Segtree {

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!

Give Us Feedback on APIO 2017 - Land of the Rainbow Gold!