Thank you for understanding, and we hope you enjoyed the rest of the problems :D
2096A - Wonderful Sticks
Idea: SanguineChameleon
Create your own test cases and solve them! What can you observe?
What is the length of the $$$n$$$-th stick?
- If $$$s_{n - 1} = \texttt{ \lt }$$$, then $$$a_n = 1$$$, because the $$$n$$$-th stick must be shorter than all the other sticks.
- If $$$s_{n - 1} = \texttt{ \gt }$$$, then $$$a_n = n$$$, because the $$$n$$$-th stick must be longer than all the other sticks.
Can we do something similar for the remaining sticks?
Yes! Remove the $$$n$$$-th stick, and then solve for the remaining $$$n - 1$$$ sticks.
We can make similar observations about the $$$(n - 1)$$$-th stick.
Then, remove the $$$(n - 1)$$$-th stick, and solve for the remaining $$$n - 2$$$ sticks, and so on.
So the algorithm is as follows:
- Initialize an array $$$b = [1, 2, \ldots, n]$$$. This represents the lengths of the remaining sticks.
- For each $$$i$$$ from $$$n - 1$$$ to $$$1$$$:
- If $$$s_i = \texttt{ \lt }$$$, then set $$$a_{i + 1} = \min(b)$$$.
- If $$$s_i = \texttt{ \gt }$$$, then set $$$a_{i + 1} = \max(b)$$$.
- Now remove $$$a_{i + 1}$$$ from $$$b$$$, and continue.
- In the end, we have $$$1$$$ remaining element in $$$b$$$. This is the value of $$$a_1$$$.
The time complexity of this solution is $$$O(n^2)$$$.
We can notice that at any point, $$$b$$$ has the form $$$[l, l + 1, \ldots, r]$$$.
So we can represent $$$b$$$ using two integers $$$l$$$ and $$$r$$$:
- When we remove $$$\min(b)$$$, we increase $$$l$$$ by $$$1$$$.
- When we remove $$$\max(b)$$$, we decrease $$$r$$$ by $$$1$$$.
Now the time complexity of our solution is $$$O(n)$$$.
#include <bits/stdc++.h>
using namespace std;
void test() {
int n;
cin >> n;
string s;
cin >> s;
int l = 1;
int r = n;
vector<int> a(n);
for (int i = n - 2; i >= 0; i--) {
if (s[i] == '<') {
a[i + 1] = l;
l++;
}
if (s[i] == '>') {
a[i + 1] = r;
r--;
}
}
a[0] = l;
for (int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int i = 0; i < t; i++) {
test();
}
return 0;
}
2096B - Wonderful Gloves
Idea: SanguineChameleon
Let's look at the third test case in the example. We have $$$k = 2$$$, and the answer is $$$x = 303$$$. If we take out $$$302$$$ gloves, then it's possible that we only have matching pairs of $$$1$$$ color.
How can we generalize this fact for any $$$k$$$ and $$$x$$$?
If we take out $$$(x - 1)$$$ gloves or fewer, then it's possible that we only have at most $$$(k - 1)$$$ matching pairs of different colors.
So we can solve the problem as follows:
- Let $$$y$$$ be the maximum number of gloves we can take out so that there are at most $$$(k - 1)$$$ matching pairs of different colors. Then the answer to the problem is $$$x = y + 1$$$.
Set $$$m = k - 1$$$. Now we need to find the maximum number of gloves so that there are at most $$$m$$$ matching pairs of different colors.
Try solving it for $$$m = 0$$$ first.
When $$$m = 0$$$, we want to find the maximum number of gloves so that there are no matching pairs.
Therefore, for each color $$$i$$$, we can either take all the left gloves, or all the right gloves. So we should choose the type with more gloves.
Formally, let $$$a_i = \max(l_i, r_i)$$$. Then the maximum number of gloves we can take is $$$y = a_1 + a_2 + \ldots + a_n$$$.
Now, using the solution for $$$m = 0$$$, solve it for $$$m = 1$$$. Then solve it for $$$m = 2$$$, and so on.
When $$$m = 0$$$, we take $$$a_i$$$ gloves of color $$$i$$$. So we're left with $$$b_i = \min(l_i, r_i)$$$ gloves of color $$$i$$$ that we haven't taken.
To get from $$$m = 0$$$ to $$$m = 1$$$, we can additionally form matching pairs of $$$1$$$ color. Therefore, we can choose a color $$$i$$$, and take the remaining $$$b_i$$$ gloves. So we should choose the color $$$i$$$ with the maximum value of $$$b_i$$$.
In other words, for $$$m = 1$$$, the maximum number of gloves we can take is $$$y = a_1 + a_2 + \ldots + a_n + \max(b_1, b_2, \ldots, b_n)$$$.
To get from $$$m = 0$$$ to $$$m = 2$$$, we can additionally form matching pairs of $$$2$$$ different colors. Therefore, we can choose two different colors $$$i$$$ and $$$j$$$, and take the remaining $$$b_i + b_j$$$ gloves. So we should choose the two colors $$$i$$$ and $$$j$$$ with the maximum value of $$$b_i + b_j$$$.
We can generalize this idea for any $$$m$$$.
So the algorithm is as follows:
- Set $$$m = k - 1$$$.
- For each $$$i$$$ from $$$1$$$ to $$$n$$$, let $$$a_i = \max(l_i, r_i)$$$ and $$$b_i = \min(l_i, r_i)$$$.
- Set $$$y = a_1 + a_2 + \ldots + a_n$$$.
- Sort the values of $$$b$$$ in descending order.
- Add the $$$m$$$ largest values of $$$b$$$ to $$$y$$$.
- The answer is $$$x = y + 1$$$.
The time complexity of this solution is $$$O(n \log n)$$$.
#include <bits/stdc++.h>
using namespace std;
void test() {
int n, k;
cin >> n >> k;
int m = k - 1;
vector<int> l(n);
for (int i = 0; i < n; i++) {
cin >> l[i];
}
vector<int> r(n);
for (int i = 0; i < n; i++) {
cin >> r[i];
}
vector<int> a(n), b(n);
long long y = 0;
for (int i = 0; i < n; i++) {
a[i] = max(l[i], r[i]);
b[i] = min(l[i], r[i]);
y += a[i];
}
sort(b.begin(), b.end(), greater<>());
for (int i = 0; i < m; i++) {
y += b[i];
}
long long x = y + 1;
cout << x << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int i = 0; i < t; i++) {
test();
}
return 0;
}
2096C - Wonderful City
Idea: thenymphsofdelphi
We are given an $$$n \times n$$$ matrix of positive integers. There are two types of operations we can perform:
- When we hire worker $$$i$$$ from company A, let's call it row operation $$$i$$$.
- When we hire worker $$$j$$$ from company B, let's call it column operation $$$j$$$.
Each row and column operation can be performed at most once.
After performing the operations, the matrix must satisfy the following:
- Horizontal Condition: No two horizontally adjacent elements are the same.
- Vertical Condition: No two vertically adjacent elements are the same.
Suppose the matrix does not satisfy the Horizontal Condition, so there is a position $$$(i, j)$$$ such that $$$h_{i,j} = h_{i, j + 1}$$$.
What operations can we perform to fix this? Don't worry about other positions for now. We just want $$$h_{i,j} \neq h_{i, j + 1}$$$.
We can either:
- Only perform column operation $$$j$$$, and increase $$$h_{i, j}$$$ by $$$1$$$;
- Or only perform column operation $$$(j + 1)$$$, and increase $$$h_{i, j + 1}$$$ by $$$1$$$.
Notice that when we perform row operation $$$i$$$, we increase both $$$h_{i, j}$$$ and $$$h_{i, j + 1}$$$ by $$$1$$$. Therefore, the difference between the two elements does not change.
Formally, when we perform row operation $$$i$$$, the value $$$d = h_{i, j} - h_{i, j + 1}$$$ does not change.
From our previous observations, we see that:
- Only column operations affect the Horizontal Condition.
- Only row operations affect the Vertical Condition.
So we can solve for the Horizontal Condition and the Vertical Condition independently.
Using DP, we will calculate:
- The minimum total cost of the row operations required to satisfy the Vertical Condition.
- The minimum total cost of the column operations required to satisfy the Horizontal Condition.
To get the answer, we add the two costs.
Let $$$dp(i, x)$$$ be the minimum total cost of the row operations required so that:
- The first $$$i$$$ rows of the matrix satisfy the Vertical Condition.
- If $$$x = 0$$$, then we do not perform row operation $$$i$$$.
- If $$$x = 1$$$, then we perform row operation $$$i$$$.
If it is impossible, then $$$dp(i, x) = \infty$$$.
Our base cases are $$$dp(1, 0) = 0$$$ and $$$dp(1, 1) = a_1$$$.
For $$$i \gt 1$$$, initialize $$$dp(i, x)$$$ to $$$\infty$$$. Our $$$dp(i, x)$$$ will depend on some $$$dp(i - 1, y)$$$.
Now we need to check if row $$$(i - 1)$$$ and row $$$i$$$ satisfy the Vertical Condition:
- The elements in row $$$i - 1$$$ are: $$$(h_{i - 1, 1} + y), (h_{i - 1, 2} + y), \ldots, (h_{i - 1, n} + y)$$$.
- The elements in row $$$i$$$ are: $$$(h_{i, 1} + x), (h_{i, 2} + x), \ldots, (h_{i, n} + x)$$$.
If no two vertically adjacent elements are the same, then:
- For $$$x = 0$$$, set $$$dp(i, x) = \min(dp(i, x), dp(i - 1, y))$$$.
- For $$$x = 1$$$, set $$$dp(i, x) = \min(dp(i, x), dp(i - 1, y) + a_i)$$$.
The minimum total cost required so that the entire matrix satisfies the Vertical Condition is $$$\min(dp(n, 0), dp(n, 1))$$$.
Similarly, we can solve for the Horizontal Condition.
The time complexity of this solution is $$$O(n^2)$$$.
To avoid repetition, we can solve for the Horizontal Condition by transposing the matrix and treating it as the Vertical Condition instead.
#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e18;
long long solveHor(int n, vector<vector<int>>& h, vector<int>& a) {
vector<vector<long long>> dp(n, vector<long long>(2, INF));
dp[0][0] = 0;
dp[0][1] = a[0];
for (int i = 1; i < n; i++) {
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
bool ok = true;
for (int j = 0; j < n; j++) {
ok &= (h[i - 1][j] + y != h[i][j] + x);
}
if (ok) {
if (x == 0) {
dp[i][x] = min(dp[i][x], dp[i - 1][y]);
}
if (x == 1) {
dp[i][x] = min(dp[i][x], dp[i - 1][y] + a[i]);
}
}
}
}
}
return min(dp[n - 1][0], dp[n - 1][1]);
}
void transpose(int n, vector<vector<int>>& h) {
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
swap(h[i][j], h[j][i]);
}
}
}
void test() {
int n;
cin >> n;
vector<vector<int>> h(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> h[i][j];
}
}
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<int> b(n);
for (int i = 0; i < n; i++) {
cin >> b[i];
}
long long horCost = solveHor(n, h, a);
transpose(n, h);
long long verCost = solveHor(n, h, b);
long long totalCost = horCost + verCost;
if (totalCost >= INF) {
cout << -1 << '\n';
}
else {
cout << totalCost << '\n';
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int i = 0; i < t; i++) {
test();
}
return 0;
}
2096D - Wonderful Lightbulbs
Idea: thenymphsofdelphi
What can we say about the number of lightbulbs that are turned on for any valid configuration in the input?
Can the number of lightbulbs that are turned on be even?
The number of lightbulbs that are turned on is always odd.
This is because we start with exactly one lightbulb turned on. Every operation changes the state of $$$4$$$ lightbulbs, which is an even number. So no matter what operations we perform, we will always have an odd number of lightbulbs turned on.
Let's use the idea of parity to come up with stricter conditions.
Consider the lightbulbs on the vertical line $$$x = c$$$. What can we say about the number of lightbulbs that are turned on?
Suppose the treasure is buried at position $$$(s, t)$$$.
- If $$$c = s$$$, then the line $$$x = c$$$ has an odd number of lightbulbs turned on.
- If $$$c \neq s$$$, then the line $$$x = c$$$ has an even number of lightbulbs turned on.
This is because every operation $$$(u, v)$$$ changes the state of $$$4$$$ lightbulbs: $$$(u, v)$$$, $$$(u, v + 1)$$$, $$$(u + 1, v - 1)$$$, $$$(u + 1, v)$$$.
- $$$2$$$ of them are on the vertical line $$$x = u$$$.
- $$$2$$$ of them are on the vertical line $$$x = u + 1$$$.
From our previous observations, we can uniquely determine the value of $$$s$$$. Can we do the same for the value of $$$t$$$?
Consider the lightbulbs on the diagonal line $$$x + y = c$$$. What can we say about the number of lightbulbs that are turned on?
Suppose the treasure is buried at position $$$(s, t)$$$.
- If $$$c = s + t$$$, then the line $$$x + y = c$$$ has an odd number of lightbulbs turned on.
- If $$$c \neq s + t$$$, then the line $$$x + y = c$$$ has an even number of lightbulbs turned on.
This is because every operation $$$(u, v)$$$ changes the state of $$$4$$$ lightbulbs: $$$(u, v)$$$, $$$(u, v + 1)$$$, $$$(u + 1, v - 1)$$$, $$$(u + 1, v)$$$.
- $$$2$$$ of them are on the diagonal line $$$x + y = u + v$$$.
- $$$2$$$ of them are on the diagonal line $$$x + y = u + v + 1$$$.
So, to summarize, we find two lines:
- The vertical line that has an odd number of lightbulbs turned on
- The diagonal line that has an odd number of lightbulbs turned on
The intersection of these two lines is the position of the treasure.
#include <bits/stdc++.h>
using namespace std;
void test() {
int n;
cin >> n;
map<int, int> cntVer, cntDiag;
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
cntVer[x]++;
cntDiag[x + y]++;
}
int s;
for (auto [c, cnt]: cntVer) {
if (cnt % 2 == 1) {
s = c;
break;
}
}
int t;
for (auto [c, cnt]: cntDiag) {
if (cnt % 2 == 1) {
t = c - s;
break;
}
}
cout << s << " " << t << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int i = 0; i < t; i++) {
test();
}
return 0;
}
2096E - Wonderful Teddy Bears
Idea: SanguineChameleon
First, we'll treat all the black teddy bears as $$$0$$$ and all the pink teddy bears as $$$1$$$.
So we are given a binary array of length $$$n$$$. In one operation, we can choose three consecutive elements and sort them in ascending order. Now we need to find the minimum number of operations required to sort the array.
There are four possible types of operations, depending on the values of the elements:
- Operation A: $$$(0, 1, 0) \rightarrow (0, 0, 1)$$$
- Operation B: $$$(1, 0, 0) \rightarrow (0, 0, 1)$$$
- Operation C: $$$(1, 0, 1) \rightarrow (0, 1, 1)$$$
- Operation D: $$$(1, 1, 0) \rightarrow (0, 1, 1)$$$
Let's think of a greedy solution first. Which operations are better than others?
We can evaluate an operation by how much it reduces the number of inversions in the array:
- Operation A reduces the number of inversions by $$$1$$$.
- Operation B reduces the number of inversions by $$$2$$$.
- Operation C reduces the number of inversions by $$$1$$$.
- Operation D reduces the number of inversions by $$$2$$$.
Therefore, ideally, we'd only perform operations B and D.
Let $$$x$$$ be the number of inversions in the original array. Then the answer is at least $$$\left\lceil \frac{x}{2} \right\rceil$$$.
Suppose we keep performing operations B and D until we can no longer do so. What will the array look like?
The array will have the form $$$[0, 0, \ldots, 0, 0, 1, 0, 1, 0, \ldots 1, 0, 1, 0, 1, 1, \ldots, 1, 1]$$$.
In other words, the array will consist of:
- A (possibly empty) sequence of consecutive $$$0$$$'s;
- A (possibly empty) sequence of alternating $$$1$$$'s and $$$0$$$'s;
- And a (possibly empty) sequence of consecutive $$$1$$$'s.
Since the array has a sequence of alternating $$$1$$$'s and $$$0$$$'s, we should think about parity.
Let $$$a$$$ be the number of $$$0$$$'s in the entire array, and $$$b$$$ be the number of $$$0$$$'s in the even positions.
When the array is sorted, all the $$$0$$$'s will be at the beginning of the array. So in the end, $$$b = \left\lfloor \frac{a}{2} \right\rfloor$$$.
Consider how each type of operation changes the value of $$$b$$$:
- Operation A either increases or decreases the value of $$$b$$$ by $$$1$$$.
- Operation B does not change the value of $$$b$$$.
- Operation C either increases or decreases the value of $$$b$$$ by $$$1$$$.
- Operation D does not change the value of $$$b$$$.
Therefore, we can only use operations A and C to change the value of $$$b$$$.
Let $$$d = \lvert \, \left\lfloor \frac{a}{2} \right\rfloor - b \, \rvert$$$. Then we need at least $$$d$$$ operations of type A or type C.
After these $$$d$$$ operations, the array will have $$$(x - d)$$$ inversions. We can show that $$$(x - d)$$$ must be even.
Then, we perform $$$\frac{x - d}{2}$$$ operations of type B or type D to reduce the number of inversions to $$$0$$$.
So the answer to the problem is: $$$d + \frac{x - d}{2} = \frac{x + d}{2}$$$.
#include <bits/stdc++.h>
using namespace std;
void test() {
int n;
cin >> n;
string s;
cin >> s;
long long x = 0;
int a = 0;
int b = 0;
for (int i = n - 1; i >= 0; i--) {
if (s[i] == 'B') {
a++;
if ((i + 1) % 2 == 0) {
b++;
}
}
if (s[i] == 'P') {
x += a;
}
}
int d = abs(a / 2 - b);
cout << (x + d) / 2 << '\n';
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int i = 0; i < t; i++) {
test();
}
return 0;
}
2096F - Wonderful Impostors
Idea: SanguineChameleon
Let's call a set of statements satisfiable if it's possible that all of them are true.
How do we check if a set of statements is satisfiable?
For each statement of the form $$$0\,a_l\,a_r$$$, assign all viewers from $$$a_l$$$ to $$$a_r$$$ as crewmates. Then, assign the rest of the viewers as impostors. Now check if all statements of the form $$$1\,b_l\,b_r$$$ are true.
When a segment of statements $$$[s_l, s_r]$$$ is satisfiable, what can we say about other segments of statements?
If $$$[s_l, s_r]$$$ is satisfiable, then $$$[s_l + 1, s_r]$$$ and $$$[s_l, s_r - 1]$$$ are also satisfiable.
We'll use the two pointers method. For each $$$s_r$$$, let $$$low(s_r)$$$ be the smallest $$$s_l$$$ such that $$$[s_l, s_r]$$$ is satisfiable. To answer a question $$$s_l\,s_r$$$, we just check that $$$s_l \geq low(s_r)$$$.
When we increment $$$s_r$$$, we will add statement $$$(s_r + 1)$$$. So we must increment $$$s_l$$$ and remove statements from the beginning of the segment until $$$[s_l, s_r + 1]$$$ is satisfiable.
Now we need to efficiently check if we can add a new statement to our current set of statements.
Let's rephrase how to determine if a set of statements is satisfiable.
For statements of the form $$$0\,a_l\,a_r$$$, we'll call $$$[a_l, a_r]$$$ a $$$0$$$-segment.
Similarly, for statements of the form $$$1\,b_l\,b_r$$$, we'll call $$$[b_l, b_r]$$$ a $$$1$$$-segment.
When $$$0$$$-segments overlap and form a larger segment, we'll call it a $$$0$$$-component.
Then, a set of statements is satisfiable if there does not exist a $$$1$$$-segment that is fully covered by a $$$0$$$-component.
When we add a $$$1$$$-segment $$$[b_l, b_r]$$$, we need to check if it will be fully covered by a $$$0$$$-component.
For each $$$i$$$ from $$$1$$$ to $$$n$$$, let $$$count(i)$$$ be the number of $$$0$$$-segments that contain viewer $$$i$$$.
Then, we can add $$$[b_l, b_r]$$$ if $$$\min(count(b_l), count(b_l + 1), \ldots, count(b_r)) = 0$$$.
The values of $$$count(i)$$$ can be maintained using a segment tree.
When we add a $$$0$$$-segment $$$[a_l, a_r]$$$, it might merge several $$$0$$$-components. So first we need to find the $$$0$$$-component $$$[c_l, c_r]$$$ that contains $$$[a_l, a_r]$$$:
- $$$c_l$$$ is the smallest value such that $$$\min(count(c_l), count(c_l + 1), \ldots, count(a_l)) \gt 0$$$.
- $$$c_r$$$ is the largest value such that $$$\min(count(a_r), count(a_r + 1), \ldots, count(c_r)) \gt 0$$$.
Both of these values can be found by performing a walk on the segment tree.
Now we need to check if there's a $$$1$$$-segment that's fully covered by $$$[c_l, c_r]$$$.
Sort all the $$$1$$$-segments in the input by ascending value of $$$b_r$$$.
Then, for all segments that satisfy $$$b_r \leq c_r$$$, find the one with largest value of $$$b_l$$$. If $$$b_l \geq c_l$$$, then $$$[b_l, b_r]$$$ is fully covered by $$$[c_l, c_r]$$$.
We can maintain another segment tree with prefix-max queries.
2096G - Wonderful Guessing Game
Idea: SanguineChameleon
First, try solving it if Alice doesn't ignore any queries.
We can represent the queries using a table. Let's look at the second test case in the example:
| $$$1$$$ | $$$2$$$ | $$$3$$$ | $$$4$$$ | $$$5$$$ |
|---|---|---|---|---|
| $$$\texttt{R}$$$ | $$$\texttt{L}$$$ | $$$\texttt{L}$$$ | $$$\texttt{R}$$$ | $$$\texttt{N}$$$ |
| $$$\texttt{R}$$$ | $$$\texttt{N}$$$ | $$$\texttt{R}$$$ | $$$\texttt{L}$$$ | $$$\texttt{L}$$$ |
| $$$\texttt{L}$$$ | $$$\texttt{N}$$$ | $$$\texttt{R}$$$ | $$$\texttt{R}$$$ | $$$\texttt{L}$$$ |
Each row is a query. Column $$$x$$$ contains Alice's responses if her number was $$$x$$$.
Let's treat $$$\texttt{L}$$$ as $$$-1$$$, $$$\texttt{R}$$$ as $$$1$$$, and $$$\texttt{N}$$$ as $$$0$$$.
| $$$1$$$ | $$$2$$$ | $$$3$$$ | $$$4$$$ | $$$5$$$ |
|---|---|---|---|---|
| $$$1$$$ | $$$-1$$$ | $$$-1$$$ | $$$1$$$ | $$$0$$$ |
| $$$1$$$ | $$$0$$$ | $$$1$$$ | $$$-1$$$ | $$$-1$$$ |
| $$$-1$$$ | $$$0$$$ | $$$1$$$ | $$$1$$$ | $$$-1$$$ |
Then, our strategy works if each row has a sum of $$$0$$$ and all $$$n$$$ columns are distinct.
Since there are only $$$3$$$ possible values, we need at least $$$q = \left\lceil \log_3(n) \right\rceil$$$ queries. In fact, this lower bound can be achieved.
We generate all $$$3^{q}$$$ possible columns: $$$[x_1, x_2, \ldots, x_q]$$$, where $$$x_i \in$$$ $$$\text{\{}$$$$$$-1, 0, 1$$$$$$\text{\}}$$$.
Now we need to choose $$$n$$$ of them so that they sum to $$$0$$$.
To do this, we can choose one pair of columns at a time:
- First, we choose $$$[x_1, x_2, \ldots, x_q]$$$;
- Then, we choose $$$[-x_1, -x_2, \ldots, -x_q]$$$.
We see that each pair of columns sums to $$$0$$$.
If $$$n$$$ is odd, we can include $$$[0, 0, \ldots, 0]$$$.
Now let's try to solve the original problem. For our strategy to work, it must satisfy the following:
- Each row has a sum of $$$0$$$.
- No two columns are the same.
- No two columns differ by exactly $$$1$$$ element.
To achieve this, we only need $$$1$$$ additional query.
Here's another way to think about it:
- For each column, no matter which element is ignored, we should be able to uniquely determine the missing value.
We use the same solution as before, but with $$$1$$$ more element:
- For each column $$$[x_1, x_2, \ldots, x_q]$$$, add an element $$$x_{q + 1}$$$ such that $$$(x_1 + x_2 + \ldots + x_{q + 1})\mod 3 = 0$$$.
Because the sum of each column is $$$0$$$ modulo $$$3$$$, we can uniquely recover any missing element.
2096H - Wonderful XOR Problem
Idea: SanguineChameleon
Is this FFT?
Let's consider the XOR convolution. Given two polynomials $$$A(x)$$$ and $$$B(x)$$$ with degree at most $$$(2^{m} - 1)$$$, the XOR convolution $$$C(x) = A(x) \star B(x)$$$ is defined as follows:
To efficiently compute the XOR convolution, we can use FWHT.
First, let $$$s(k, i) = (-1)^{\text{popcount}(k\,\&\,i)}$$$.
Then, $$$F(A(x))$$$ is defined as follows:
Given $$$A^{\,\prime}(x) = F(A(x))$$$, we can uniquely determine $$$A(x) = F^{-1}(A^{\,\prime}(x))$$$ using the inverse of FWHT.
To compute $$$F(A(x))$$$ and $$$F^{-1}(A^{\,\prime}(x))$$$, we can use SOS DP.
Define the dot product $$$D(x) = A(x) \cdot B(x)$$$ as follows: $$$\displaystyle [x^k]D(x) = [x^k]A(x) \cdot [x^k]B(x)$$$
We can show that $$$F(A(x) \star B(x)) = F(A(x)) \cdot F(B(x))$$$ for any two polynomials $$$A(x)$$$ and $$$B(x)$$$.
Let's solve the problem. For each interval $$$[l_i, r_i]$$$, let $$$A_i(x) = x^{l_i} + x^{l_i + 1} + \ldots + x^{r_i}$$$.
We want to find $$$A_1(x) \star A_2(x) \star \ldots \star A_n(x)$$$. To do this, we'll compute $$$F^{-1}(F(A_1(x)) \cdot F(A_2(x)) \cdot \ldots \cdot F(A_n(x)))$$$.
We can note that $$$\displaystyle [x^k]F(A_i(x)) = \sum_{l_i \leq j \leq r_i} s(k, j)$$$
Let $$$f(k, r) = \displaystyle \sum_{0 \leq j \leq r} s(k, j)$$$. Then $$$\displaystyle [x^k]F(A_i(x)) = f(k, r_i) - f(k, l_i - 1)$$$.
Now we need to find a way to compute $$$f(k, r)$$$ efficiently.
Let $$$p$$$ be the ($$$0$$$-indexed) position of the least significant bit of $$$k$$$.
Let $$$c = \left\lfloor \frac{r}{2^{p + 1}} \right\rfloor$$$. Then $$$f(k, r) = \displaystyle f(k, c \cdot 2^{p+1} - 1) + \sum_{c \cdot 2^{p + 1} \leq j \leq r} s(k, j)$$$
Due to cancellation of terms, we have $$$f(k, c \cdot 2^{p+1} - 1) = 0$$$.
We can also see that $$$s(k, j) = s(2^p, j) \cdot s\left(\left\lfloor \frac{k}{2^{p + 1}} \right\rfloor, \left\lfloor \frac{j}{2^{p + 1}} \right\rfloor\right) = s(2^p, j) \cdot s\left(\left\lfloor \frac{k}{2^{p + 1}} \right\rfloor, c\right)$$$
Therefore, $$$\displaystyle f(k, r) = \left(\sum_{c \cdot 2^{p + 1} \leq j \leq r} s(2^p, j)\right) \cdot s\left(\left\lfloor \frac{k}{2^{p + 1}} \right\rfloor, c\right)$$$.
Returning to $$$F(A_i(x))$$$, we get:
where:
- $$$a_i$$$ and $$$b_i$$$ are constants independent of $$$k$$$.
- $$$k^{\,\prime} = \left\lfloor \frac{k}{2^{p + 1}} \right\rfloor$$$, $$$c_i = \left\lfloor \frac{r_i}{2^{p + 1}} \right\rfloor$$$, and $$$d_i = \left\lfloor \frac{l_i - 1}{2^{p + 1}} \right\rfloor$$$.
But wait! This is just $$$[x^{k^{\,\prime}}]F(a_i \cdot x^{c_i} + b_i \cdot x^{d_i})$$$. So we'll let $$$B_i(x) = a_i \cdot x^{c_i} + b_i \cdot x^{d_i}$$$.
Therefore,
Now we need to find a way to compute $$$F(B_1(x) \star B_2(x) \star \ldots \star B_n(x))$$$ efficiently.
First, we can normalize each polynomial: $$$a \cdot x^c + b \cdot x^d = (a + b \cdot x^{c\,\oplus\,d}) \star x^c$$$
Now all polynomials have the form $$$a_i + b_i \cdot x^{c_i}$$$.
Next, we can convolve polynomials with matching powers of $$$x$$$:
Now the expression is of the form:
Finally, we have:
This can be computed using SOS DP.









Thanks for the fast tutorial!
In problem D, Why can't we first fix the y and then find x? See 316293937. A vast majority of submitted solutions can be easily hacked by just mirroring the coordinates given in sample testcase 2 along the x = y line. Was the decision to disable hacks taken during the contest or before the contest?
Edit: Just woke up. Realized my mistake. I misread the question. We had to make a ladder shape, not a plus shape. I initially solved the problem using the flawed logic and it passed 2/4 sample testcases which led to this confusion.
The problem isn't symmetric with respect to x and y...
They wrote an incorrect tester.
Edit: The tester code is correct. The problem itself is not symmetric about x and y.
why were hacks disabled for problem D?
There is almost no way to check if these $$$n$$$ lightbulbs can be achieved
why?
How would you do that?
Translate the operation to flip the $$$2 \times 2$$$ square. So $$$(a, b)$$$ is equivlent to $$$(a, 0), \ (0, b), \ (0, 0)$$$. So a state is possible if and only if my code don't gives RE:
Wait! Does that mean testcases wre not generated and eventually written, solved and added.
I guess there are some patterns which are achievable without just making some small amount of moves, but all tests are some special cases that testsetters have thought of
Could you give a concrete example that, no initial point exists for the lightbubs with odd number lit?
Update. Found. $$$(0, 0), (0, 1), (0, 2)$$$.
From the solution of the problem we can see, that if there is more than one diagonal, that has odd lamps on it, or more than one vertical line, then it's not achievable
Could you see my proof?
Instead of explicitly giving the n points, why not give some number of operations and the initial lightbulb coordinates? This way it will always be a valid input, with the caveat that it's achievable by some O(n) operations at most, so nothing super crazy.
Wow! Such a well written editorial(and fast). Thanks to everyone involved!
Can anyone explain problem B? I couldn't get after reading editorial :| (me dumb)
think in reverse , let's say for test case (in which ans is 481) if you take total no. of gloves you picked == 329. how are you going to prove it wrong . in next take pick gloves == (97 + 77 + 50 + 87 + 74 ) . try to prove it wrong. now observe if you just pick one extra glove you will have atleast one pair . what minimum number is required to pick , such that you have atleast 2 different pairs(color) gloves. hint ==> try to pick 95 and one more from any of remaining gloves.
yes, so the answer should be 425 and not 481... how is that ?
i also did the same mistake as we have to take the worst possible case. in the worst case, we would pick the maximum of li,ri. eg: i=1, max(97,95)=97 now if we take 1 glove from 95 the, it would be 1 pair. but we will not do that now. lets just pick the max of li,ri (97+77+50+87+74 = 385). now to have 2 pairs, in the worst case we have to pick max of remaining li,ri (or max(min(li,ri)) as we have counted max(li,ri) already. in that case we pick 95 gloves and picking 1 more glove will guarantee us 2 pairs. so (385+95+1)=481.
I wonder how did you verify your tests for problem D? Is the condition for validity just checking that the number of groups of (x + y) with odd number of elements is 1, and the number of groups of x with odd number of elements is 1? I think that there should be other conditions satisfied.
I think they manually created tests, that's why hacks are disabled because they can't come with polynomial time solution, without the condition that it is indeed possible to get a point.
Yes, that is the one of explanations. But I wonder, can't wrong solutions pass with these manually created tests? Although there is only answer for the task, the algorithm for reaching it may be flawed. I wonder did authors consider this?
Because of this, there is no need to verify actual reachability. It just needs to trust that the main solution generated the correct and the only answer, and simply compare it to the participant's output.
I mean that the participant's solution may be wrong, but it generates the same output as author's solution.
If the output is the same as the author's solution, then by definition the solution is correct.
Can't they do it backward? Get a treasure location and sequences of toggles.
Was problem B's statement confusing for anybody else? I couldn't figure out if they meant pairs of different color for the left and right glove or same color gloves.
hey arnav bhaiya same thing confused me also i m fresher of our college means for 481 case the ans should be 425 accd to me
damn dats crazy
In problem E, why is it always possible to perform exactly $$$\left | \left \lfloor \frac{a}{2} \right \rfloor - b \right |$$$ operations so that the number of zeros on even positions equals $$$\left \lfloor \frac{a}{2} \right \rfloor $$$?
While the array isn't sorted:
Thank you.
In the easier version of problem F where Alice doesn't ignore any queries, does this solution work?
For each bit from $$$2^0$$$ to $$$2^{\lfloor log_2 n \rfloor }$$$ , ask a query with all numbers from $$$1$$$ to $$$n$$$ which contain this bit. The order of the numbers in the query doesn't matter.
Then look at the set of queries that Alice responded with L or R to. These queries represent exactly the bits in her secret number. Thus, we know her secret number.
Do you mean G? You need to ensure that the number of integers from $$$1$$$ to $$$n$$$ that you ask in each query ($$$k$$$) is even. Moreover, the number of queries that you use is $$$\lceil \log_2 n \rceil$$$, which is unoptimal.
Yes, I meant G. Thanks for the answer -- I forgot that k has to be even and that you have to minimize the number of queries.
note to myself: one day i will solve b constantly
In problem H, in step 2.3, maybe $$$c = [\frac{r}{2^{p + 1}}]$$$?
Yes, that's correct. It's been fixed now. Thank you!
FOR D =>
We can think of the lights as functioning like an XOR operation. Every time we step on a coordinate, it toggles the light, changing its state from 0 to 1 or 1 to 0. If we step on the same coordinate again, it flips back. This behavior is like XOR, where applying the same value twice cancels it. If we observe the x-coordinates involved, they are of the form x, x, x+1, x+1. Using the XOR property (a ⊕ a = 0 and a ⊕ b ⊕ b = a), we can easily deduce the value of x by taking the XOR of all x-coordinates. This will cancel out the repeated values and give us the unique x.
However, we can’t directly apply the same logic to the y-coordinates because the XOR of y-values may not cancel out cleanly. But there’s a workaround — consider the values of x + y. These values follow a similar pattern: x + y, x + y, x + y + 1, x + y + 1. Again, the same XOR principle applies here. Taking the XOR of all x + y values will eliminate the repeated ones and leave us with the unique x + y.
Once we have both x and x + y, finding y becomes straightforward: simply subtract x from x + y, and you get y. This approach cleverly uses XOR properties and pattern recognition to deduce both coordinates, making it a neat and efficient solution to the problem.
I HOPE IT HELPS... MY SOLUTION — https://mirror.codeforces.com/contest/2096/submission/316257978
thanks for these creative problems
I am unable to grasp why horizontal and vertical operations can be solved independently in problem C. Can someone explain it in brief. Thanks in advance.
Horizontal operations can never introduce or resolve a horizontal 'conflict'. Here a conflict is a pair
(i, j)such thath[i][j-1] == h[i][j]. That's because they don't change the differenceh[i][j-1] - h[i][j]. For all the same reasons, vertical operations can never introduce or resolve a vertical 'conflict'.Many people have said in the comments that in problem D, it is not possible to verify if the given set of points is actually achievable by a set of operations, and the authors seem to think so too given that hacks are disabled. However, I believe it's actually quite easy to prove that the condition is if and only if. Let's state the problem as follows (we'll switch to the $$$(x, x+y)$$$ coordinate system and remove the special point):
Proof: By applying the operation on all points in the set $$$(x+i, y+j)$$$ with $$$0\leq i \lt w$$$ and $$$0\leq j \lt h$$$, we can use the operation to flip the corners of a rectangle $$$(x, y)$$$, $$$(x+w, y)$$$, $$$(x, y+h)$$$, $$$(x+w, y+h)$$$. While the set of points is nonempty, pick an arbitrary point $$$(x, y)$$$ in the set. Since all row and column frequencies are even, there must exist another point with the same $$$x$$$ value, and another point with the same $$$y$$$ value. We can flip the rectangle with these points as corners. Each step reduces the number of points by at least $$$2$$$, so we will eventually finish.
We had a proof that it was always achievable before the contest — in fact, all tests are generated randomly and not by hand. The main reason we disabled hacks was because of concerns over
std::unordered_maphacks. We were also aware of the $$$O(n)$$$ solution without any data structures and using only the XOR operator, but we wanted to ensure that no contestant would get hacked mid-contest.The proof was omitted from the editorial since I believed it wasn't needed to solve this problem. Sorry about the confusion!
I don't think it's really necessary. Relying on a particular inefficient implementation is a mistake that everyone should be free to make. In addition, there's a simple, faster choice with better functionality called
std::map. Hacks are good for breaking special-case-bad solutions like this.On the other hand, it makes for a terrible contest experience if there are hacks and i have to go around looking for how to hack thos particular implementation of the dictionary yet again
In the solution code of problem D
cntVer[x]++; Does this mean that if we find key x in map,add the value by 1.else the default value is 0,insert{x,0} to the map?
Seems this is a syntactic sugar.We can use map like an array.But is this code always right?
If
xis not in the map, we initialize it with value0before incrementing it.I really like this format of editorial—it allows me to go through the solution step by step when I'm stuck. After each step, I can pause and consider whether I can solve the problem at that point. I think this approach is highly effective for improving both thinking process and skill level.
I strongly recommend that editorials for other Codeforces Rounds adopt this format as well.
What a detailed editorial!Hope that contest in the future will be the same as this one.
This is one of the best editorials I have ever read. Thank you!
Great Editorial!!
Answer in steps is better than hints
Thank you for the detailed editorial! Appreciate the effort put into writing this.
Very understandable, thank you for the tutorials
!
Questions about Step 7 for problem E — Wonderful Teddy Bears:
1) What does it guarantee us that we can make operation A or operation C first d times? What if array is not sorted, but we can't make operation A or C?
2) What does it guarantee us that we can make operation B or operation D every time after first d times? What if array is not sorted, but we can't make operation B or D?
I'm not sure if I understand correctly.
If the array is not sorted, but we can't make operation A or C, the string doesn't contain "010"(operation A) or "101", so it is like "111...1000..00" (all ones are on the left of all zeros), then we can do operation B or D first.
However, no matter how we do operation B or D doesn't change $$$b$$$. $$$d = \lvert \, \left\lfloor \frac{a}{2} \right\rfloor - b \, \rvert$$$ does not change, so we must do operation A or C sooner or later, if it is necessary.
A certain number of A or C operations are necessary and do not necessarily need to be performed first.
During the contest, I come up with a solution more like "bruteforce" but maybe more understandable.
We need a stack (empty initially) and from left to right, we try to add every $$$s_i$$$ in the 0-1 string.
It means we can see $$$top$$$ and $$$s_i$$$ as a combination. More specifically, if $$$top=s_i=0$$$ we perform operation B continuously to move this "00" to the front of the sequence. The case $$$top=s_i=1$$$ is simillar. Every time we perform B or D, the Inversions of the sequence are reduced by 2.
Finally, if the stack is empty, we don't need operation A or C.
Otherwise the characters in stack will be "1010....01010". Its size is
Len.We perform operation A or C to make every four "1010" to be "1001", the final stack will be "100110011001...10011001"
Then we can certainly use only B and D to sort it.
So the number of operation A and C we performed is $$$cnt=\lfloor \frac{Len}{4} \rfloor$$$.
So the answer is
(Inversions-cnt)/2+cnt.my submission
D : https://www.youtube.com/watch?v=rslsd4aOZjA
What's wrong with this approach in problem E?
1.Bring 2 B's together in pair, eg. PBPPPB -> PBBPPP
2.After step 1, bring pair to left such that no P is in left of that pair, eg.
BPPPBBPP -> BBBPPPPP
Code
Please someone guide.
it's correct, but it depends on how join the pairs. Example: PBPBPPBPB
the tutorial of F doesn't declare about how to remove a statement from the begining, and it is not obvious actually. May anyone tell me how to remove, please?
For the statements of type 0 you do perform
add(l, r, -1).For the statements of type 1 you remove $$$l$$$ from the set $$$s_x$$$ and do
set(l, max(s[x])). (-1 if it's empty)Now the thing you probably don't understand is how to tell if the current set is good.
It's always good. But when you are trying to add a statement you need to check that condition in the editorial. If it's bad then you don't add it yet and remove the current leftmost condition. If not then you can finally add it.
316435804
Definitely RIGHT! I did thinking about how to find out the fault statements, but it is clever to maintain the correctness of the set of the statements! Thanks for your clear answer!
I understand the steps for problem E, but I can't motivate it(Particularly checking the number of 0s in the even, positions). I don't even know how you would come up with it. Can someone explain thier thought process on how you approached the problem.
During the contest, I come up with a solution more like "bruteforce" but maybe more understandable.
You can read this comment. Hope it will help.
How can we show that $$$x - d$$$ will always be even in problem E?
In the end, when you can no longer make a move of type A or C, the string will look like 00100100. At that point, only the patterns 100 or 110 will have an effect, and both contain 2 (even) inversions.
This is the best way of Editorial ever
An (unnecessarily complicated) way to generate columns for G:
Let $$$f_0(1) = \{[0]\}, f_{-1}(1) = \{[-1]\}, f_1(1) = \{[1]\}$$$, and let $$$\text{append}(S, x)$$$ be the set of all $$$v \in S$$$ with $$$x$$$ appended to them.
Then, for all $$$i \gt 1$$$, define $$$f_0$$$, $$$f_{-1}$$$, and $$$f_1$$$ inductively as follows:
We can induct with the following claims:
$huh why did mathjax break??$
To select columns, we can pick things from $$$f_0$$$ in the last layer.
Sorry SanguineChameleon, I could not understand problem E editorial. Can any1 explain the proof and why this works? I understood till step 4, that 0000..010101..01111..11 will happen. After that I am at a loss. (I am dumb and again starting CP seriously)
This is the coolest tutorial I've ever seen.
My favorite editorial's style
In the problem statement of problem A '<' symbol is defined as \lt and '>' symbol is defined as \gt. There seems to be conversion issues in the symbols or maybe its my own browser.