thanks to nifeshe for making my life easier with templates
After performing $$$z$$$ operations, the robot's $$$x$$$-coordinate is exactly $$$z$$$.
After completing any operation, the $$$x$$$-coordinate and $$$y$$$-coordinate always have the same parity.
Try to find a construction to reach any point $$$(x,y)$$$ where $$$y\le x$$$ and $$$x$$$ and $$$y$$$ have the same parity.
Notice that after performing $$$z$$$ operations, the robot's $$$x$$$-coordinate will be exactly $$$z$$$, while its $$$y$$$-coordinate cannot exceed $$$z$$$.
We will first consider the case $$$b\le a$$$, then handle the special case $$$b=a+1$$$.
Notice that the robot can reach any point $$$(x,y)$$$ where $$$0\le y\le x$$$ and $$$x$$$ and $$$y$$$ have the same parity in exactly $$$x$$$ operations. To do so, we can first move up until reaching $$$y$$$, then alternate between moving up and down.
But what if $$$x$$$ and $$$y$$$ have different parities?
In this case, we can reach $$$(x,y-1)$$$ in exactly $$$x$$$ operations, since $$$x$$$ and $$$y-1$$$ have the same parity.
Now, recall that in each operation, the robot moves vertically before moving horizontally. Therefore, we can perform one additional operation:
The robot visits $$$(x,y)$$$ during this operation, so the answer is $$$x+1$$$.
Now, let's consider the remaining cases:
- If $$$b=a+1$$$, we can use the same construction, since $$$a$$$ and $$$b$$$ have different parities. We reach $$$(a,b-1)=(a,a)$$$ in $$$a$$$ operations, then visit $$$(a,b)$$$ during the next operation. Thus, the answer is $$$a+1$$$.
- If $$$b \gt a+1$$$, reaching $$$(a,b)$$$ is impossible, since the robot can make at most $$$a+1$$$ vertical moves before leaving column $$$a$$$.
Therefore, the answer is:
- $$$-1$$$ if $$$b \gt a+1$$$.
- $$$a$$$ if $$$a$$$ and $$$b$$$ have the same parity.
- $$$a+1$$$ otherwise.
The time complexity is $$$O(1)$$$ per test case.
#include <bits/stdc++.h>
using namespace std;
void solve() {
int a, b;
cin >> a >> b;
if (b > a + 1) cout << -1 << '\n';
else if (a % 2 == b % 2) cout << a << '\n';
else cout << a + 1 << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
}
Let $$$cnt[x]$$$ be the number of cards containing $$$x$$$. Consider the smallest $$$x$$$ such that $$$cnt[x] \lt 2k$$$.
What happens if $$$cnt[x]=2k-1$$$? Can Alice and Bob have the same $$$\operatorname{mex}_k$$$?
If $$$cnt[x]\le 2k-2$$$, try finding a winning strategy for Bob by pairing cards with the same value.
Let $$$cnt[x]$$$ be the number of cards containing $$$x$$$.
We will consider the integers $$$x=0,1,2,\ldots$$$ in increasing order, and find the first $$$x$$$ such that $$$cnt[x] \lt 2k$$$.
We claim that Alice wins if and only if $$$cnt[x]=2k-1$$$.
Let's prove this by considering two cases.
Case 1: $$$cnt[x]=2k-1$$$.
We will show that it is impossible for Alice and Bob to have the same $$$\operatorname{mex}_k$$$, regardless of how they play.
Suppose both players have the same $$$\operatorname{mex}_k=y$$$. We consider three cases:
- If $$$y \lt x$$$, both players must have fewer than $$$k$$$ cards containing $$$y$$$. This is impossible because $$$cnt[y]\ge 2k$$$.
- If $$$y=x$$$, both players must again have fewer than $$$k$$$ cards containing $$$x$$$. This is impossible because $$$cnt[x]=2k-1$$$.
- If $$$y \gt x$$$, both players must have at least $$$k$$$ cards containing $$$x$$$. This is also impossible because $$$cnt[x]=2k-1 \lt 2k$$$.
Therefore, there is no possible value of $$$y$$$ for which both players have the same $$$\operatorname{mex}_k$$$.
Thus, Alice always wins, regardless of how either player plays.
Case 2: $$$cnt[x]\le 2k-2$$$.
We will show that Bob can always make both MEX values equal.
Bob can use the following strategy: pair as many cards with the same value as possible, then pair the remaining cards arbitrarily. Whenever Alice takes a card, Bob takes the other card from its pair.
This guarantees that each player receives either $$$\lfloor cnt[y]/2\rfloor$$$ or $$$\lceil cnt[y]/2\rceil$$$ cards containing any integer $$$y$$$.
Now notice that:
- For every $$$y \lt x$$$, we have $$$cnt[y]\ge 2k$$$, so both players receive at least $$$k$$$ cards containing $$$y$$$.
- For $$$y=x$$$, we have $$$cnt[x]\le 2k-2$$$, so both players receive fewer than $$$k$$$ cards containing $$$x$$$.
Therefore, both players have $$$\operatorname{mex}_k=x$$$, and Bob wins.
Thus, we only need to find the first $$$x$$$ with $$$cnt[x] \lt 2k$$$. The answer is "YES" if $$$cnt[x]=2k-1$$$, and "NO" otherwise.
The time complexity is $$$O(n)$$$ per test case.
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
vector<int> cnt(n + 1, 0);
for (int i = 0; i < n; ++i) {
int a;
cin >> a;
++cnt[a];
}
for (int x = 0; x <= n; ++x) {
if (cnt[x] < 2 * k) {
cout << (cnt[x] == 2 * k - 1 ? "YES\n" : "NO\n");
break;
}
}
}
return 0;
}
Consider the prefix XOR array $$$p$$$. A subarray $$$[l,r]$$$ has XOR $$$0$$$ if and only if $$$p_{l-1}=p_r$$$.
How does the beauty change when a prefix XOR appears for the first, second, or third time?
Try constructing a prefix XOR array where every possible value appears exactly twice, while ensuring that $$$p_{i-1}\oplus p_i\le n$$$.
Let $$$x$$$ be the greatest power of $$$2$$$ not exceeding $$$n$$$.
Define the prefix XOR array $$$p$$$ as follows:
- $$$p_0=0$$$.
- $$$p_i=a_1\oplus a_2\oplus\cdots\oplus a_i$$$.
Notice that a subarray $$$[l,r]$$$ has XOR equal to $$$0$$$ if and only if $$$p_{l-1}=p_r$$$.
Also, since $$$a_i\le n \lt 2x$$$, none of the elements has a set bit greater than or equal to $$$2x$$$. Therefore, every prefix XOR belongs to the range $$$[0,2x-1]$$$.
Now, let's see what happens when we add a new prefix XOR $$$p_i$$$:
- If $$$p_i$$$ has never appeared before, no new subarray with XOR $$$0$$$ is created, so the beauty increases by $$$1$$$.
- If $$$p_i$$$ has appeared exactly once, exactly one new subarray with XOR $$$0$$$ is created, so the beauty stays the same.
- If $$$p_i$$$ has appeared at least twice, the beauty decreases.
Since there are only $$$2x$$$ possible prefix XOR values, and $$$p_0=0$$$ already exists, the maximum possible beauty is at most $$$2x-1$$$.
To achieve this beauty with the maximum possible length, we want every prefix XOR from $$$0$$$ to $$$2x-1$$$ to appear exactly twice.
This gives us $$$4x$$$ prefix XORs, corresponding to an array of length $$$4x-1$$$.
Now, let's show how to construct such an array.
Instead of constructing $$$a$$$ directly, we will construct the prefix XOR array $$$p$$$, then recover $$$a$$$ using $$$a_i=p_{i-1}\oplus p_i$$$.
First, visit all integers from $$$0$$$ to $$$x-1$$$ in increasing order, then visit them again in decreasing order:
After that, do the same for all integers from $$$x$$$ to $$$2x-1$$$:
Clearly, every integer from $$$0$$$ to $$$2x-1$$$ appears exactly twice.
We only need to verify that every $$$a_i=p_{i-1}\oplus p_i$$$ is at most $$$n$$$.
Notice that:
- The XOR of any two integers from $$$[0,x-1]$$$ is smaller than $$$x$$$.
- The XOR of any two integers from $$$[x,2x-1]$$$ is also smaller than $$$x$$$, since their highest set bits cancel.
- The only jump between these two ranges is from $$$0$$$ to $$$x$$$, whose XOR is exactly $$$x$$$.
Therefore, every element of $$$a$$$ is at most $$$x\le n$$$, so our construction is valid.
Since every prefix XOR appears exactly twice, we have exactly $$$2x$$$ subarrays with XOR $$$0$$$. Thus, the beauty is
which achieves the maximum possible beauty with the maximum possible length.
The time complexity is $$$O(n)$$$ per test case.
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n;
cin >> n;
int x = 1;
while (2 * x <= n) x *= 2;
vector<int> p;
for (int i = 0; i < x; i++) p.push_back(i);
for (int i = x - 1; i >= 0; i--) p.push_back(i);
for (int i = x; i < 2 * x; i++) p.push_back(i);
for (int i = 2 * x - 1; i >= x; i--) p.push_back(i);
cout << (int)p.size() - 1 << '\n';
for (int i = 1; i < (int)p.size(); i++)
cout << (p[i] ^ p[i - 1]) << " \n"[i == (int)p.size() - 1];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
}
Notice that $$$|f(s+1)-f(s)|\le 1$$$. How can we use this property?
Prove that the maximum value of $$$f(s)$$$ is achieved at some $$$s=l_i$$$.
After finding a position $$$pos$$$ with maximum $$$f(pos)$$$, try using binary search to find a position $$$s$$$ where $$$f(s)=k$$$, even though $$$f(s)$$$ is not monotonic.
Let $$$f(s)$$$ be the number of infected positions in the segment $$$[s,s+m-1]$$$.
First, notice that when we increase $$$s$$$ by $$$1$$$, we remove the position $$$s$$$ and add the position $$$s+m$$$.
Therefore, $$$f(s)$$$ can change by at most $$$1$$$ when we increase $$$s$$$ by $$$1$$$.
This observation will be useful later.
Now, let's find the maximum possible value of $$$f(s)$$$.
We claim that the maximum is achieved at some $$$s=l_i$$$.
To see why, consider any starting position $$$s$$$:
- If $$$s$$$ is infected but is not the beginning of an infection interval, we can move $$$s$$$ to the left by $$$1$$$. Since the newly added position is infected, $$$f(s)$$$ cannot decrease. We can repeat this until reaching the beginning of that interval.
- If $$$s$$$ is not infected, we can move $$$s$$$ to the right by $$$1$$$. Since the removed position is not infected, $$$f(s)$$$ cannot decrease. We can repeat this until reaching the beginning of the next infection interval.
Therefore, it is sufficient to check $$$f(l_i)$$$ for every interval.
Let $$$mx$$$ be the maximum value we find, and let $$$pos$$$ be a position where $$$f(pos)=mx$$$.
Now, we have three cases:
- If $$$k \gt mx$$$, the answer is $$$-1$$$, since we cannot infect that many people.
- If $$$k=mx$$$, we can simply output $$$pos$$$.
- Otherwise, $$$k \lt mx$$$, and we will find a valid position using binary search.
Now, suppose $$$k \lt mx$$$. We know that $$$f(pos)=mx \gt k$$$, and we also know that $$$f(10^{15}+1)=0\le k$$$, since there are no infected positions after $$$10^{15}$$$.
Therefore, we have two positions: one where $$$f(s) \gt k$$$, and another where $$$f(s)\le k$$$.
Recall that moving $$$s$$$ by $$$1$$$ changes $$$f(s)$$$ by at most $$$1$$$. This means that somewhere between these two positions, there must be a position where $$$f(s)=k$$$.
We can find such a position using binary search!
Maintain two positions $$$l$$$ and $$$r$$$ such that $$$f(l) \gt k$$$ and $$$f(r)\le k$$$. Initially, set $$$l=pos$$$ and $$$r=10^{15}+1$$$.
Let $$$mid=\lfloor(l+r)/2\rfloor$$$.
- If $$$f(mid) \gt k$$$, set $$$l=mid$$$.
- Otherwise, set $$$r=mid$$$.
Notice that we always keep one position with $$$f(s) \gt k$$$ and another with $$$f(s)\le k$$$, so we never lose the guarantee that a valid answer exists between them.
Continue until $$$r=l+1$$$.
Now, since $$$f(l) \gt k$$$ and $$$f(r)\le k$$$, and these positions are adjacent, we must have $$$f(r)=k$$$. Therefore, we can output $$$r$$$.
Note that $$$f(s)$$$ does not need to be monotonic for this binary search to work! We only need the fact that $$$f(s)$$$ changes by at most $$$1$$$ between consecutive positions.
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n;
long long m, k;
cin >> n >> m >> k;
vector<long long> l(n), r(n), pref(n + 1);
for (int i = 0; i < n; i++) {
cin >> l[i] >> r[i];
pref[i + 1] = pref[i] + r[i] - l[i] + 1;
}
auto f = [&](long long s) -> long long {
long long e = s + m - 1;
int i = lower_bound(r.begin(), r.end(), s) - r.begin();
int j = upper_bound(l.begin(), l.end(), e) - l.begin() - 1;
if (i > j) return 0;
long long ans = pref[j + 1] - pref[i];
ans -= max(0LL, s - l[i]);
ans -= max(0LL, r[j] - e);
return ans;
};
long long mx = -1, pos = 0;
for (int i = 0; i < n; i++) {
long long cur = f(l[i]);
if (cur > mx) {
mx = cur;
pos = l[i];
}
}
if (k > mx) {
cout << -1 << '\n';
return;
}
if (k == mx) {
cout << pos << '\n';
return;
}
long long low = pos, high = 1000000000000001LL;
while (high - low > 1) {
long long mid = (low + high) / 2;
if (f(mid) > k) low = mid;
else high = mid;
}
cout << high << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
}
Try solving a relaxed version where we can split any element, even if it is smaller than or equal to $$$k$$$.
Show that we can perform all splits before any erasures, then process the erasures in reverse order.
Binary search on the number of splits. When processing backward, consider the largest remaining element: should we erase it or split it?
First, let's solve a relaxed version of the problem, where we are allowed to split any element, even if it is already small enough to be erased.
Let's find a greedy solution for this relaxed version.
Suppose we perform exactly $$$c$$$ splits. Each split increases the number of elements by $$$1$$$, so we will need $$$n+c$$$ erasures.
Therefore, the total number of operations is
Now, notice that we can always perform all splits before any erasures.
We can prove this using an exchange argument. If a split happens after an erasure, we can swap these two operations. The split remains valid because splitting is always allowed in our relaxed version, and the erasure remains valid because $$$k$$$ only increases.
By repeatedly applying this argument, we can rearrange the operations into the following order:
Now, let's binary search on the number of splits $$$c$$$.
To check whether $$$c$$$ splits are sufficient, we will process the erasures in reverse order, starting from the last erasure and moving toward the first.
The value of $$$k$$$ at the last operation is
Let $$$H$$$ be the largest remaining element.
We have two cases:
If $$$H \gt S$$$, we must split $$$H$$$, since we cannot erase it now, and we certainly cannot erase it at any earlier operation, where $$$k$$$ is even smaller.
If $$$H\le S$$$, we claim that it is optimal to erase $$$H$$$ now.
Let's prove the second case.
Consider an optimal solution that does not erase $$$H$$$ at this moment. There are two possibilities:
It erases $$$H$$$ at an earlier operation. In this case, we can simply swap that erasure with the current one. This is valid because $$$H\le S$$$, and the other element, being no larger than $$$H$$$, can also be erased earlier.
It splits $$$H$$$ instead. Suppose it erases some smaller element $$$y$$$ at this moment. We can instead erase $$$H$$$ and split $$$y$$$. Since $$$y\le H$$$, the two elements produced by splitting $$$y$$$ are no larger than those produced by splitting $$$H$$$. Therefore, we can perform the same subsequent operations without making anything harder. If the element erased at this moment was itself produced by splitting $$$H$$$, we can simply erase $$$H$$$ instead and avoid those splits.
Thus, in both cases, there exists an optimal solution that erases $$$H$$$ now.
This proves our greedy strategy.
Whenever we erase an element, we decrease $$$S$$$ by $$$1$$$, since we move to the previous erasure. Whenever we split an element, we replace it with two elements equal to $$$\lceil H/2\rceil$$$, without changing $$$S$$$.
If we need more than $$$c$$$ splits, the check fails. Otherwise, it succeeds.
We can implement this efficiently using a frequency array to maintain the remaining elements.
Now, let $$$X$$$ be the minimum number of operations for the relaxed problem.
Clearly, the answer to the original problem is at least $$$X$$$, since the relaxed problem allows everything the original problem allows.
However, notice something important about our greedy construction: we only split an element when $$$H \gt S$$$.
Since $$$S$$$ is at least the value of $$$k$$$ when that split would actually happen, we also have $$$H \gt k$$$ at that moment.
Therefore, every split performed by our greedy solution is valid in the original problem as well!
This means our solution to the relaxed problem is also a valid solution to the original problem, so the minimum number of operations is the same for both.
Finally, if $$$c$$$ is the minimum number of splits found by binary search, the answer is
The time complexity is $$$O(n\log n)$$$ per test case, and the space complexity is $$$O(n)$$$.
#include <bits/stdc++.h>
using namespace std;
void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n);
int mx = 0;
for (int &x : a) {
cin >> x;
mx = max(mx, x);
}
vector<int> freq(mx + 1);
for (int x : a) freq[x]++;
auto ok = [&](int c) {
vector<int> cnt = freq;
int alive = n, used = 0, H = mx;
long long S = 1LL * k + n + 2LL * c - 1;
while (alive > 0) {
while (cnt[H] == 0) H--;
if (H <= S) {
cnt[H]--;
alive--;
S--;
} else {
if (used == c) return false;
cnt[H]--;
cnt[(H + 1) / 2] += 2;
alive++;
used++;
}
}
return true;
};
int l = 0, r = max(0, mx - k);
while (l < r) {
int mid = (l + r) / 2;
if (ok(mid)) r = mid;
else l = mid + 1;
}
cout << n + 2 * l << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
}
Notice that we can always make the array beautiful using at most $$$2$$$ operations.
Let $$$mx$$$ be the maximum element. Try setting $$$a_1=mx$$$ or $$$a_n=mx$$$.
If neither works, can we make the array beautiful by changing one occurrence of $$$mx$$$ to something?
First, notice that we can always make the array beautiful using at most $$$2$$$ operations, by setting $$$a_1=a_n=10^9$$$.
Now, let's check whether the array is already beautiful. If it is, the answer is $$$0$$$.
Otherwise, the answer must be either $$$1$$$ or $$$2$$$.
We claim that if the answer is $$$1$$$, at least one of the following three operations makes the array beautiful.
Let $$$mx$$$ be the maximum element of the array, and let $$$pos$$$ be any position such that $$$a_{pos}=mx$$$.
The three operations are:
- Set $$$a_1=mx$$$.
- Set $$$a_n=mx$$$.
- Set $$$a_{pos}=1$$$.
We can simply try each operation and check whether the resulting array is beautiful. If any of them works, the answer is $$$1$$$. Otherwise, the answer is $$$2$$$.
Now, let's prove why these three cases are sufficient.
Imagine the array looks like this:
Notice that setting $$$a_1=mx$$$ makes the entire left side covered by good pairs, while setting $$$a_n=mx$$$ does the same for the right side.
If neither operation makes the array beautiful, this means there are still uncovered positions on both sides.
Therefore, if we want to fix everything using only one operation, we must somehow fix both sides at once.
The only remaining possibility is to decrease a maximum element, allowing good pairs to connect across it.
Suppose changing this maximum element to some value $$$X$$$ makes the array beautiful.
We claim that changing it to $$$1$$$ would also work.
Why? Any new good pair that spans this position remains good if we decrease its value even further.
The other possibility is that the new value $$$X$$$ creates two good pairs, one on each side, looking like this:
Here, the middle $$$X$$$ is the element we changed, and both pairs are good.
If we decrease the middle element to $$$1$$$, the two pairs can be replaced by one larger good pair:
Thus, decreasing the maximum element to $$$1$$$ is sufficient.
lets also note if that max element occurs more than once this is useless.
This proves that checking our three operations is enough to find an optimal solution.
Finally, checking whether an array is beautiful can be implemented in $$$O(n\log n)$$$ using several approaches, or in $$$O(n)$$$ using a monotonic stack.
Since we perform only a constant number of checks, the overall time complexity is $$$O(n)$$$ per test case.
#include <bits/stdc++.h>
using namespace std;
bool beautiful(vector<int>& a) {
int n = a.size();
vector<int> st, diff(n + 1);
for (int i = 0; i < n; i++) {
while (!st.empty() && a[st.back()] < a[i])
st.pop_back();
if (!st.empty() && a[st.back()] == a[i]) {
diff[st.back()]++;
diff[i + 1]--;
}
st.push_back(i);
}
int cur = 0;
for (int i = 0; i < n; i++) {
cur += diff[i];
if (cur == 0) return false;
}
return true;
}
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
if (beautiful(a)) {
cout << 0 << '\n';
return;
}
int pos = max_element(a.begin(), a.end()) - a.begin();
int mx = a[pos];
auto check = [&](int i, int x) {
int old = a[i];
a[i] = x;
bool ok = beautiful(a);
a[i] = old;
if (ok) {
cout << 1 << '\n';
cout << i + 1 << ' ' << x << '\n';
}
return ok;
};
if (check(0, mx)) return;
if (check(n - 1, mx)) return;
if (check(pos, 1)) return;
cout << 2 << '\n';
cout << 1 << ' ' << mx << '\n';
cout << n << ' ' << mx << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) solve();
}
Case 1: There are no $$$1\times 1$$$ pieces
First, let's consider the case where the grid contains no $$$1\times 1$$$ pieces.
Notice that either every piece has width at least $$$2$$$, or every piece has height at least $$$2$$$. Otherwise, a row segment of height $$$1$$$ and a column segment of width $$$1$$$ would intersect to form a $$$1\times 1$$$ piece.
Since we can transpose the grid, we may assume that every piece has width at least $$$2$$$.
We will show that a valid filling always exists.
Step 1: Fill the first row of every piece.
Consider a piece of width $$$w$$$, whose first row is row $$$i$$$ of the grid (using 0-based indexing).
- If $$$i$$$ is even, fill it with $$$[1,2,\ldots,w]$$$.
- Otherwise, fill it with $$$[w,w-1,\ldots,1]$$$.
When $$$w$$$ is odd, we additionally swap the middle element with the element before it in the decreasing order.
For example, when $$$w=5$$$, the two arrangements are:
$$$[1,2,3,4,5]$$$ and $$$[5,3,4,2,1]$$$.
Notice that these arrangements differ at every position. This ensures that vertically adjacent first rows have different values, while horizontally adjacent pieces also have different values at their boundaries.
Step 2: Fill the remaining rows.
Now, fill the remaining cells row by row, from top to bottom.
For the $$$k$$$-th row of a piece of width $$$w$$$ (0-based), we need to place the numbers
Normally, we place them in increasing order. However, if the first number equals the cell immediately to its left, we instead move the last number to the beginning.
Since $$$w\ge 2$$$, this always avoids horizontal conflicts.
Also, different rows of the same piece use completely different ranges of numbers, so vertical adjacency inside each piece is automatically satisfied. Across horizontal cuts, the first-row construction handles pieces of height $$$1$$$, while taller pieces have different ranges at the boundary.
Thus, every piece contains exactly the required numbers, and all adjacent cells are different. Therefore, a valid filling always exists when there are no $$$1\times 1$$$ pieces.
Case 2: There are $$$1\times 1$$$ pieces
First, let's determine when it is impossible to fill the grid.
Suppose there are two $$$1\times 1$$$ pieces in the same row, with only $$$1\times 2$$$ pieces between them.
For example:
Since every $$$1\times 1$$$ piece must contain $$$1$$$, the first cell is forced to be $$$1$$$. This forces the next $$$1\times 2$$$ piece to be $$$[2,1]$$$, and the same applies to every following piece.
We end up with:
Clearly, this is invalid because the last two adjacent cells both contain $$$1$$$.
The same argument applies vertically to two $$$1\times 1$$$ pieces with only $$$2\times 1$$$ pieces between them.
We claim that these are the only cases where a valid filling is impossible.
Let's prove this by constructing a valid filling whenever neither case occurs.
Step 1: Fill all thin pieces.
First, put $$$1$$$ in every $$$1\times 1$$$ piece.
Now, let's fill all $$$1\times y$$$ and $$$y\times 1$$$ pieces.
We will only explain the construction for horizontal pieces, since vertical pieces can be handled in exactly the same way.
Consider any two $$$1\times 1$$$ pieces in the same row.
Since our impossible condition does not occur, there must be at least one $$$1\times y$$$ piece between them with $$$y\ge 3$$$.
Choose the first such piece from the left and call it the turning point.
We fill the pieces between the two $$$1\times 1$$$ pieces as follows:
- For every piece before the turning point, write its numbers in decreasing order.
- For every piece after the turning point, write its numbers in increasing order.
- For the turning point itself, use the order $$$[y,1,2,3,\ldots,y-1]$$$.
Notice that this guarantees that adjacent cells contain different numbers, including across the boundaries of the pieces.
For portions of the row before the first $$$1\times 1$$$ piece, after the last one, or rows containing no $$$1\times 1$$$ pieces, we can simply choose a suitable increasing or decreasing order.
We apply the same construction vertically to fill all remaining $$$y\times 1$$$ pieces. 
Step 2: Fill the rows containing $$$1$$$.
Notice that by choosing our coloring patterns consistently in the previous step, the already-colored cells in each partially filled row contain the same value.
Now, consider every partially filled row whose already-colored cells contain $$$1$$$.
We can fill the gaps between these $$$1$$$ s using exactly the same turning-point construction from Step 1.
This fills all such rows while ensuring that horizontally adjacent cells contain different numbers. 
Step 3: Fill the remaining cells.
Now, let's consider the remaining unfilled rows.
The important observation is that these rows can be handled independently, since the vertical constraints have already been taken care of by our construction.
Furthermore, every gap we need to fill has the same value, say $$$x$$$, on both its left and right boundaries.
Therefore, we only need to arrange the remaining numbers inside each piece so that adjacent values are different and neither boundary creates a conflict.
We can use the same idea as before: arrange the values in increasing or decreasing order, and use a turning point whenever necessary.
Since the required values are available and the vertical constraints are already satisfied, we can fill all remaining gaps.
Thus, we have constructed a valid filling whenever neither of the two impossible configurations occurs, completing the proof.
2271H2 - Personal Issues (Hard Version)
Editorial will be Added when Axial isn't tired :(
if you have any non slop solutions please comment them below
~~~~
~~~~








Auto comment: topic has been updated by employed (previous revision, new revision, compare).
Some people passed H2 by bitset.
Sorry :(
damn C was annoying, I had to write a stresstester and print out a bunch of values to find it, Binary searrching inside poison blocks were fun in D! Nice round tbh <3
Auto comment: topic has been updated by employed (previous revision, new revision, compare).
Brilliant contest.
Additionally, during contest I remembered the problem 2255D which involves binary searching the answer with time back-tracking trick while checking. It helps a lot for solving problem E.
God, he cooked the whole Jordanian community
I wasn't able to implement D, but it was a nice problem.
yeahh same. when will the result come of this contest? i mean rating change.
Really Nice approach for C . I just bruteforced and found a pattern . Couldnt prove entire thing tho
D could also be solved in O(n) using slope trick
Can you explain in details the idea please? It's like a convex hull trick?
Here is my attempt at explaining the idea:
An equivalent problem
You are going to a place that has been bombarded and your goal is to find a place with a depth of exactly $$$k$$$, the bombs were dropped in many ranges $$$l_i$$$ to $$$r_i$$$ and a bomb dropped on position $$$x$$$ increases the depth of the range $$$x-m+1 ... x$$$ by $$$1$$$. This will help visualize the function $$$f(s)$$$ better.
Considering a single range $$$l_i...r_i$$$
Instead of storing the depth of the terrain, the main objective is to store the slope of the terrain, for convenience of implementation, let's define $$$g(s):=f(s+1)-f(s)$$$, where $$$g(s)$$$ will represent the 'angle' of the terrain between positions $$$s$$$ and $$$s+1$$$.
Now, there are four key positions we are interested on: The point where we start entering a hole (let's call it $$$a$$$), the point where we reached the bottom of the hole (let's call it $$$b$$$), the point where we start going up again (let's call it $$$c$$$) and the point where we left the hole (let's call it $$$d$$$). between points $$$a$$$ and $$$b$$$, the slope is $$$1$$$ because the depth increases by $$$1$$$ every step; between points $$$b$$$ and $$$c$$$, the slope is $$$0$$$; and between the points $$$c$$$ and $$$d$$$ the slope is $$$-1$$$.
$$$a$$$ is $$$l_i-m$$$; $$$b$$$ and $$$c$$$ are either $$$l_i$$$ or $$$r_i-m+1$$$ in any order; and $$$d$$$ is $$$r_i$$$+1$. To store this function, we will create another function $$$h(s):=g(s)-g(s-1)$$$ (again, this is just for easier implementation). After this, we'll see that $$$g(s)=0$$$, except for the points $$$a$$$, $$$b$$$, $$$c$$$, and $$$d$$$. For this points, $$$g(s)$$$ will be $$$1$$$, $$$-1$$$, $$$-1$$$, $$$1$$$, respectively.
Implementation with many ranges
Let $$$f_i$$$(s) be the function $$$f(s)$$$ considering only the range $$$l_i$$$ to $$$r_i$$$; $$$g_i(s)$$$ be the slope of $$$f_i(s)$$$; and $$$h_i(s)$$$, the slope of $$$g_i(s)$$$, then it's easy to see that $$$f(s)$$$ is just the sum of $$$f_i(s)$$$ for all $$$0 \lt =i \lt n$$$ (assuming 0-indexing), and the same is true for $$$g(s)$$$ and $$$h(s)$$$. Based on this observation, for every range $$$l_i...r_i$$$, we can add $$$1$$$ to $$$h(l_i-m)$$$, subtract 1 from $$$h(l_i)$$$, subtract $$$1$$$ from $$$h(r_i-m+1)$$$ and add $$$1$$$ to $$$h(r_i)$$$.
Obtaining $$$f(s)$$$
Now that we have $$$h(s)$$$, we can construct $$$g(s)$$$, which is just the prefix sum of $$$h(s)$$$.
To get $$$f(s)$$$ we only need some critical points (I don't know how to properly refer to them), these are the points where the slope changes, which are the points $$$a$$$, $$$b$$$, $$$c$$$ and $$$d$$$ of every range $$$l_i...r_i$$$. If we obtain $$$f(s)$$$ for those points, let $$$s1$$$ and $$$s2$$$ be any two critical points with no other critical points in between, we can get $$$f(x)$$$ for any $$$s1 \lt =x \lt =s2$$$ using any formula of a straight line.
Final step and additional notes
To obtain the answer, simply go through every pair of adjacent critical points and check if the answer might be between them, if so, report it. If you never found it, the answer is -1. If $$$k=0$$$, then just output a huge number.
Since we only need $$$f(s)$$$ of those critical points at the end, we only need to compute $$$g(s)$$$ and $$$h(s)$$$ for those critical points.
To sort the points so that we can use prefix sum, I used an array of size 4 of queues to store all points $$$a$$$, $$$b$$$, $$$c$$$ and $$$d$$$. At the end I just combined them as in merge sort.
It could also be solved in a single for loop after the critical points are sorted since to get $$$f(s)$$$ we only need $$$g(s)$$$ and some additional variables to keep track of the prefix sum; same for $$$g(s)$$$, except we need $$$h(s)$$$; and to get $$$h(s)$$$ we only need the $$$h(s)$$$ of previous points.
Sorry if my explanation was very long, I just didn't know how to make it more compact without leaving a lot of stuff unexplained. I hope my explanation was helpful. Also, sorry for taking 2 days in answering.
395356822 similar idea i think but my implementations is ass
Thanks for this contest, i have finally become a pupil
congrats!!
C can also be solved with gray codes, making this the first time I've actually used them in a contest
Can you explain how please?
Construct the gray code with all bits up to x (greatest power of 2 not exceeding n as in editorial). Then, repeat this list twice. You can use this list as the prefix xor array because it contains all values from 0 to 2^x-1 exactly twice. When you reconstruct the original array by taking the xor of adjacent elements, each element in the original array will have a single bit set which will not exceed n
Given that you've established that all numbers from 0 to 2x — 1 must arise exactly twice in the prefix xor of the array (from the editorial).
Gray codes define an encoding where adjacent numbers differ by a singular bit. To recover the original array; we take adjacent xors, the highest value any such value can take is x <= n.
A gray code for [0, 2^n — 1] can be written using [0, 2^n — 1] itself in some order, which also holds cyclically, i.e, the last and the first differ by a bit too (helps with the occuring twice thingy)
I couldn't give the contest but after the contest I did the same firstly I tried with prefix xors as 0,0,1,1.... which didn't work then did graycode of all of them. 0 1 0 2 0 1 0 4 0 1 0 2 0 1 0 8 0 1 0 2 0 1 0 4 0 1 0 2 0 1 0 , gives such a beautiful pattern , I could probably write a recursive solution ngl.
gray codes are a cute way to solve Div2C
ikr :)
I used them too, finally the digital electronic's course was useful
When employed writes a contest. reference: https://youtu.be/Z9q-tzW_dzo?t=3644
Binary search over non-monotonous function in D is a beautiful trick!
how??, like i have used binary search separately on the non increasing and non decreasing part
Check out my submission for problem C, this is a recursive approach.
There is a much simpler (in the sence of implemenentation) O(n) solution to D.
The solution uses the sliding window technique. We start with $$$begin=end=n$$$
If the the last segemnt has size >= k, then $$$f(r_n-k+1)=k$$$. If not, we can move our $$$begin$$$ pointer left (and adding $$$holes+=l_{beg}-r_{beg-1}-1)$$$ until either $$$r_{end}-l_{beg}+1-holes$$$ >= k or $$$r_{end}-l_{beg}+1 \gt m$$$.
In the first case, let $$$filled=r_{end}-l_{beg}+1-holes$$$, then if $$$r-l+1-(filled-k) \leq m$$$ then $$$f(l_{beg}+filled-k)=f(l_{beg})-(filled-k)=filled-(filled-k)=k$$$, because 1. $$$[l_{beg},l_{beg}+filled-k]$$$ is all ones, because in the last step $$$filled_{old} \lt k$$$, so $$$r_{beg}-l_{beg}+1=filled-filled_{old} \gt filled-k$$$ and $$$[l_{beg}+m,l_{beg}+m+filled-k]$$$ is all zeros, because we know this it to the right of out $$$[beg,end]$$$ range ($$$r-l+1-(filled-k) \leq m$$$), and it's before the beggining of the next range, because either $$$end=n$$$ and there is no next range, or the next range was removed before at some $$$beg' \gt beg$$$. Then $$$r_{end+1}-l_{beg'}+1 \gt m$$$ and since it didn't terminate $$$r_{end+1}-l_{beg'}+1-holes_{beg'...end+1} \lt k$$$. If $$$holes_{beg'...end+1} \lt m-k$$$, then $$$r_{end+1}-l_{beg'}+1-(m-k) \lt k$$$ => $$$r_{end+1}-l_{beg'}+1 \lt m$$$ which is false, so $$$holes_{beg'...end+1} \gt m-k$$$ => $$$holes_{beg...end+1} \gt m-k$$$ (because $$$beg \lt beg'$$$) => $$$holes+l_{end+1}-r_{end}+1 \gt m-k$$$ => $$$l_{end+1} \gt m-k+r_{end}+1-holes=l_{beg}+filled-k+m$$$, so the start of the next range is greater then the end of the range used by $$$f(l_{end}+filled-k)$$$.
In the second case we move $$$end$$$ to the left and update $$$holes-=l_{end}-r_{end-1}-1$$$
If this procedure doesn't find any suitable $$$f(s)$$$'s, then none exitst (because this means that all $$$f(s) \lt k$$$)
My submission: 394022211
HARDforces
Exactly!
For $$$F$$$, is this correct? "First, notice that we can always make the array beautiful using at most 2operations, by setting $$$a_1=a_n=10^9$$$." If there is $$$10^9$$$ in the middle, how to do it?
If $$$ a_p=10^9$$$,$$$[1,p]$$$ and $$$[p,n]$$$ are also ok.
got it. thanks.
A good starting point for problem C is to use Gray code
Just need to construct a Gray code sequence, and then reverse and copy it again
Although a lot less beautiful, E can be solved with a binary search on the amount of splits and a Fenwick tree for the check https://codeforces.me/contest/2271/submission/394037143
E was dayuuumm amazin', i thought of the binary search way, like if check(<=mid splits) is true, then check(<=mid+1 splits) is also true, so it is monotonic, but unable to figure out the "GREEDYNESS" of the check fn! :|
There's an alternate solution to problem B that I think some could find useful. The optimal strategy for Alice is to get as many lower-numbered cards as she can, and the optimal strategy for Bob is to copy Alice's moves (thus, also getting as many lower-numbered cards as she can). The reason why both players desire lower-numbered cards is because that is what changes the k-MEX the most.
Therefore, we can directly simulate how the game would play out. This runs in (I believe) O(n^2), which is slower than the tutorial, but passes all test cases nonetheless.
can be easily optimized to O(N) just store count in cnt array then find first i with cnt[i] < k
For C problem, I did this simple idea imo
Idea: Use only powers of two and zeros. A subarray's XOR is 0 only if every bit in it is turned on and then off again. We arrange the bits so that to turn a bit off, you're forced to fire a another bit in between, which stays on. So no subarray with a nonzero element has XOR 0, and the only zero-XOR subarrays are single zeros (
l = rwitha[l] = 0).Construction: Let
kbe the highest bit ofn. Take length2 ^ (k + 2) - 1. Put1in the middle,2in the middles of the halves,4in the middles of the quarters, and so on. Leftover cells are0. Forn = 2:0 2 0 1 0 2 0.In any subarray, the smallest bit appears exactly once, so the XOR is nonzero. Zeros are never adjacent.
Answer: beauty =
(2 ^ (k + 2) - 1) - 2 ^ (k + 1) = 2 ^ (k + 1) - 1, which is optimal. There are only2 ^ (k + 1)possible prefix XOR values, and each can appear at most twice.Here is my code: recursion code for printing the pattern in C
nifeshe can you add H1 and H2 pls, i guess Axial has already rested
Cannot :(
nifeshe can i submit my idea-code and if it passes you'll add my explanation and code to this editorial plsssss (i think my idea is beatifull)
Auto comment: topic has been updated by employed (previous revision, new revision, compare).
couldn`t solve D during contest, but I upsolved it and it is now one of my favourite problems OAT! Nice round :)
I think the last part of the editorial's proof of problem E is incomplete. It shows that the greedy splits are legal in the original problem, but does not prove that the construction performs exactly $$$c$$$ splits.
For example, when $$$n=1,k=0,a=[1]$$$, the minimum feasible $$$c$$$ is $$$1$$$, but the greedy check performs $$$s=0$$$ splits.
Here is how we can complete the proof.
Let $$$c$$$ be the minimum feasible value. Suppose the greedy construction performs $$$s \lt c$$$ splits, leaving a sorted array $$$b_1\le \cdots\le b_{n+s}$$$. Since the check succeeds, we have
By the minimality of $c$, the array cannot satisfy $$$b_j\le k+s+j-1$$$ for every $$$j$$$, otherwise $$$s$$$ splits would already suffice.
Let $$$i$$$ be the first index violating this inequality. Then
Thus, we can legally append a split of $b_i$ after the previous $$$s$$$ splits.
Replace $$$b_i$$$ with two copies of $$$q=\lceil b_i/2\rceil$$$, obtaining an array $$$d$$$ (before sorting). We claim that
Indeed:
For $j<i$: $$$d_j=b_j\le k+s+j-1\le k+2c-s+j-2$$$.
For $$$j=i$$$: $$$d_i=q\le \max(1,b_i-1)\le k+2c-s+i-2$$$, since $$$c \gt s$$$.
For $$$j=i+1$$$: $$$d_j=q\le b_i\le k+2c-s+i-1$$$.
For $$$j \gt i+1$$$: $$$d_j=b_{j-1}\le k+2c-s+j-2$$$.
Sorting $$$d$$$ preserves these inequalities because the right-hand sides are increasing.
Therefore, we can increase $$$s$$$ by $$$1$$$ while maintaining the invariant. Repeating this process until $$$s=c$$$, we obtain
which guarantees that all remaining elements can be erased after exactly $c$ splits.
The initial greedy splits are also legal in the original problem, since they occur only when $$$H \gt S\ge k+2c-s\ge k+s$$$.
Thus, a valid construction with exactly $$$c$$$ splits exists in the original problem, completing the proof.
C was simply brilliant coudnt solve without the help of editorial though but learned lot
Great Editorial!