
Introduction
------------

In this problem you are given some nested circles. When drawing a circle it
originally is red. When a circle is drawn all circles within its area turn the
opposite color. You get a reward or penalty for each circle when it changes
state. Determine a permutation to draw the circles that maximizes reward
but comes first lexicographically.

Observations
------------

This problem yields itself to analysing it's cases. The tricky part is to not
get caught up in case by case analysis when coding a solution. It's very easy
to try and code a solution that handles all cases explicitly but then misses
a special case. Coding the solution in a more general way can reduce bugs and
make this problem much more pleasant to solve.

The first observation is that the nested circles form a forest of trees. The problem
statement itself could even be modified for the input to be a tree but I found it
much easier to explain the problem elegantly in terms of circles. Building the
tree from the circles in N^2 time is easy.

Another observation is that it is always possible to get a score of zero.
Simply draw the roots, then each of its children and so on in a bfs or dfs order.

Imagine for a minute that for all circles A=B. For this simplied version we
can make the following observations:
   1. If A is positive then we want it to change state as much as possible.
      Simply put draw this node before all of it's ancestors.
   2. If A is negative then we want to change state never.
      Draw this type of node after all of it's ancestors.
   3. If A is zero then it doesn't matter when the state changes!

The next observation is that it is very easy to rework the scoring. Instead of
accruing reward for it's decendants when a circle is drawn, give the reward based
on the number of ancestors in the tree left to draw. The cost function is easier
to deal with in this kind of thinking. Notice which circles that are left to draw
doesn't matter. The only thing that matters is the sum of circles left.

Notice that any permutation is possible. This fact is important because that means
that any combination of parents left to draw after a circle is drawn is also 
possible.

This simplifies the problem down considerably. We know that each node has K 
ancestors. We need to find a number for each node in the interval [0, K]
that maximizes the reward. This number is the number of ancestors left to draw.
This can be done with simple iteration in N^2 time after precomputing the
number of parents for each circle. Precomputing the parent count can be done 
with DFS.

The answer for the reward is simply the maximum of all the nodes reward functions.
Finding the maximum answer is easy. Recovering the permutation is the tricky
part of this problem.

There are two types of nodes that are interesting to consider. The ones that are
cyclic and acyclic. Cyclic nodes occur when A+B=0. For these nodes reach their 
maximum every turn (A=0 B=0) or on an alternating time step (A=5 B=-5), (A=-1 B=1).
It is very easy to determine the cycle.

For the acyclic nodes their maximum occurs in either the first two changes or
the last two changes. In other words the optimal value V occurs when
V=0, V=1, V=K-1, or V=K. When A+B is positive the max change happens at
K-1 or K. When A+B is negative the max change happens at 0 or 1. (depending on
if A is positive)

In other words it is easy to compute maximum reward in linear time.

O(N^2 log N) solution
---------------------

The solution to this problem is somewhat similar to incremental topological
sort for recovering a lexicographically first solution. There are two important
differences however. The first is that candidate nodes for the next number
in the permutation make be removed from being candidate nodes in the next
iteration. This property occurs in cyclic nodes. The second difference is that
when a node reaches its last possible V value then it must be draw before
any of it's ancestors.

The algorithm to recover the lexicographically first permutation is simple:

while (hasNodesLeft()):
   findNode():
      find node that is at a maximum V value, comes lexicographically first by 
      label and doesn't have ancestors on their last maximum V value.
   remove node from active nodes
   add node to permutation

Just implement find node correctly in O(N log N). 

To make things easier on ourselves we can do a dfs on the forest to obtain
the preorder and postorder timings of each node. This is a very common trick
and will enable us to quickly determine if one node is an ancestor of another.
Simply a node is an ancestor if its preorder number is in the interval 
[pre,post] of another node.

Now finding the node can be done in two steps:
1. Step through the nodes in label order.
      Find all nodes that that maximize V value in the current state.
      if the node is on it's last V value then place it's preorder number
         in a TreeSet called special (or multiset in c++).
2. Step through candidate nodes in label order.
      call special.higher(preorder[curNode]) or its c++ equivalent.
      This will get the first preorder number strictly higher than the
      current node's preorder number.
      if special.higher(preorder[curNode]) > postorder[curNode]
         return curNode

Now you have a simple solution for this problem if N=5000

O(N log N) solution
-------------------

I've been playing around with the idea of an O(N log N) solution to this problem
for quite a while. I don't have a definite solution to the problem yet but here 
I will gives some of the ideas I came up with to try and solve the problem for
the bounds when N=10^5. These ideas can potentially be morphed into an extra
separate problem (I have some ideas or different problems with this bound and
will list them here) or this problem made into an extra hard version with N=10^5 
bounds if the judge crew is smarter than me and can fill in the holes. :)

First thing that can happen is the forest of trees can be reconstructed in
O(N log N) time. This can be done with a sweep. Sweep from left to right
when the sweep line enters the start of a circle add the top and bottom of
the curve to a binary tree data structure. (easy to do with treeset or multiset)
The value of the curve changes when the sweepline moves but the relative
positioning of the curves remains invariant. When a circle is first reached we 
can cast a line upward from the top of curve. This is done with TreeSet.higher.
Notice we will hit no curve, the bottom of a curve or a top of a curve.
Keep track for each node the node that it hit and which side of the curve that
was hit.

At the end of the sweep we have a data structure that looks something like this:

                   o
                  /
                 /
                /
               /
              /
             o-------o------o
                    / \
                   /   \
                  o     o

The edges either point to the parent of the tree (what we want) or one of the
siblings. If the ray cast hit the bottom of a curve the edge is a sibling edge
and if it hit the top of a curve we are nested inside the circle. 

Then to recover the real tree do the following:

loop through each node:
   walk sibling pointers until a sibling with a parent is reached.
      when a node is reached put it on a stack
      when updating sibling pointers pull them off the stack and
      update their parent pointer

The cost of doing this is amortized O(N) since a parent pointer is only
updated once and the search stops once a parent is reached. This is somewhat
similar to path compression in union find.

Now we have a tree that looks something like this:

                   o
                  /|\
                 / | \
                /  |  \
               /   |   \
              /    |    \
             o     o     o
                  / \
                 /   \
                o     o

We can work with this data structure.

*---------------------*
| Alternative problem |
*---------------------*

I'm going to take a side bar here and talk about an alternative problem that
can be giving for N=10^5 using this idea. This can be used if the judging crew
wanted to fork off this idea into a separate problem. 

Given the nested circles and an ordering that they are draw. Determine for each
circle at the time it is draw the number of circles it is nested in and the
number of circles contained in it's area.

This can be done by constructing the tree from the nested circles and then using
two binary indexed trees (fenwick trees) to update and calculate the desired values.

The problem uses the same preorder postorder trick described above and the updates
happen on those fenwick trees.

This problem is uninteresting as it does not require observations or taking
advantage of special properties of the problem to solve. But if there weren't
many submissions for problems this year it can make a decent "filler" problem.

The story can be something based on empires on earth and how certain ones were
formed of previous empires or something. Feel free to modify this idea in any
way to make a more interesting problem.

-----------------------

Now back to solving the original problem "Alchemy". We already know that for each
node the V values for each node can be calculated in linear time. We just need
a way to speed up findNode to O(log N). 

Using the preorder postorder trick this problem can be changed to work on intervals.
In the interval form of the problem we can easily update all nodes in a given range.
It would be very easy to activate and deactivate cyclic nodes every timestep.
In each node simply keep the two minimum labels in the data structure flip the
min labels when updating a change of state for a subtree. You can use
interval trees, treaps or splay trees to implement this idea. The tricky part
is satisfying the second condition. We need some way to only poll nodes that
do not have a node in their subtree on their last valid V value. This is a way
to get a suboptimal solution. I think there is a way to still modify the data
structure to handle this property but I have yet to figure it out.

I recommend looking down this path for a solution if the set looks too easy. This
version could become an interesting hard problem if the judges can figure it out.

Good Luck! :D
