POI - Cards
Authors: Dong Liu, Dustin Miao
Time Complexity:
Explanation
We can use a segment tree to solve this problem.
For each segment tree node with the range , we will store if it's possible to arrange the cards so that we either
- don't flip card and card
- don't flip card and flip card
- flip card and don't flip card
- flip card and card
We can represent these states in a 2 by 2 matrix bool[2][2]
where the first dimension stores whether we flip card and the second dimension stores whether we flip card .
To calculate the states for a specific segment tree node, we loop through all possible states of our left child node and all possible states of our right child node . If the transition from to works, then works since we're only considering endpoints.
To perform a swap operation with index and , we simply swap the cards at and . We can just recalculate all nodes in the segment tree that are related to either or . Since there are around ranges in the segment tree that contain or , this whole swap operation takes .
Additionally, we also have to print if we can form a non-decreasing list using the cards. To do this, if any states of the root node in our segment tree (which covers ) is possible, then our answer is yes (TAK
), otherwise no (NIE
).
Implementation
C++
#include <bits/stdc++.h>using namespace std;const int N = 1 << 18;int n, q, aa[N][2];bool tt[N << 1][2][2];void pull(int i, int l, int r) {memset(tt[i], 0, sizeof(tt[i]));
Alternate Solution
We can reduce the number of states stored in the segment tree to just two:
- The minimum last value of the interval given that we take the lesser side of the first card (denote this as )
- The minimum last value of the interval given that we take the greater side of the first card (denote this as )
Note that it will always be optimal to take the lesser side of the last side given that we can take both. This, in turn, prepares the current interval with the next merging step, if applicable.
Let's denote the array of cards as , where is the front side and is the back side. Without loss of generality, assume that for all . We consider merging interval and to create interval , where corresponds to the array elements . Note that this implies corresponds to and corresponds to , where
Note that we choose to be the default value, because under our merge conditions, infinity conveniently overrides all other operators. This means that if any point of the array is discontinuous (or unable to be made into a non-decreasing sequence), node in the segment tree, which corresponds to the entire array, will also have .
Time Complexity:
Implementation
C++
#include <bits/stdc++.h>using namespace std;using ll = long long;using pll = pair<ll, ll>;#define MP make_pair#define FF first#define SS second
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!