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;56const int MAXN = 2e5, MAXSEG = (6e5 + 9) * 19 + 1;78int cnt = 1, segtree[MAXSEG], left_c[MAXSEG], right_c[MAXSEG];910struct 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!