Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
For a fixed , forget the exact values. Every element is only one of three types: , , or . The middle type is harmless filler. An interval is bad exactly when it contains at least one and at least one .
So the real question is: can we choose positions for “small” and positions for “large” so that no given interval contains both colors? Neutrals can go anywhere else. This is no longer about the array values, only about the counts and .
Look only at the colored positions after deleting neutral positions. If some interval contains both colors, then inside that interval there must be two neighboring colored positions with different colors. So it is enough to control when the color is allowed to switch.
For every position , compute : the smallest left endpoint of any interval covering ; if none covers it, set . If the previous colored position is at and you put the opposite color at , this is legal exactly when .
Use DP over the last colored position. Let be the maximum number of large-colored positions if position is colored and exactly small-colored positions have been used. Prefix maxima over make both “same color” and “switch color before ” transitions .
For a fixed , every value belongs to one of three groups:
An interval fails exactly when it contains at least one small and at least one large. Neutral values are just filler; they do not matter.
So for this , define
The question becomes:
Can we choose positions for small values and positions for large values so that no given interval contains both types?
If yes, the equal values fill the remaining positions. Clean.
Imagine deleting all neutral positions. We are left with a subsequence of colored positions, each either small or large.
If some interval contains both colors, then among the colored positions inside that interval there must be two neighboring colored positions with different colors. So instead of checking all pairs of opposite colors, we only need to know when we are allowed to switch color between two consecutive colored positions.
For each position , compute
among all intervals with . If no interval covers , set .
Now suppose the previous colored position is , and we want to color position with the opposite color.
Therefore:
Same-color transitions are always fine, because an interval containing two smalls or two larges is not a problem.
Use 0 for small and 1 for large.
Let
be the maximum number of large positions we can place if:
We also maintain prefix maxima:
This lets us choose the previous colored position quickly.
When coloring position with color :
Let
That is the number of small positions used before coloring .
Transitions:
for continuing the same color, and
for switching colors.
The fake state at position initializes both colors with zero placed elements, so the first real colored position can be either color. Slightly hacky, but it saves annoying casework.
After processing all positions, the maximum number of large positions possible with exactly small positions is
So is valid iff this value is at least . If we can place more than large positions, just turn the extras into neutral positions. Removing colored positions cannot create a bad interval, because deletion never creates a new opposite-colored pair. No magic, no weird vibes.
Lemma 1. For a fixed , an interval is invalid iff it contains at least one value and at least one value .
Proof. The interval is invalid exactly when
That is exactly the condition that some value is below and some value is above . Values equal to do not change this. QED.
Lemma 2. For a fixed , feasibility depends only on and .
Proof. By Lemma 1, only the positions of values below and above matter. All values equal to are neutral filler. QED.
Lemma 3. Let be consecutive colored positions after deleting neutral positions, and suppose their colors differ. This transition is legal iff .
Proof. If , take an interval covering whose left endpoint is . Since intervals are contiguous, it also contains , so it would contain both colors. Illegal.
If , then no interval covers both and . Otherwise that interval would cover and have left endpoint at most , which is smaller than . Contradiction. QED.
Lemma 4. A coloring is valid iff every pair of consecutive colored positions with different colors satisfies the rule from Lemma 3.
Proof. If such a consecutive pair violates Lemma 3, some interval contains both colors, so the coloring is invalid.
Conversely, suppose a coloring is invalid. Then some interval contains both colors. Look at the colored positions inside that interval in increasing order. Somewhere in that list the color changes, giving two consecutive colored positions of different colors inside the same interval. By Lemma 3, that switch violates the rule. QED.
Lemma 5. The DP computes exactly the maximum number of large positions obtainable for every number of small positions and ending color.
Proof. Consider the last colored position and its color . If the previous colored position has color , it can be any earlier colored position, represented by . If it has color , Lemma 3 says it must be before , represented by . These are exactly all legal possibilities for the previous colored position, and the transition adds the contribution of position . Induction over proves the claim. QED.
Theorem. The algorithm outputs 1 for exactly those values for which a valid rearrangement exists.
Proof. For value , Lemmas 1 and 2 reduce the problem to placing exactly small and large positions. By Lemmas 4 and 5, the DP tells us the largest number of large positions possible while using exactly small positions. If it is at least , we keep of those large positions and make the rest neutral. If it is less than , no valid placement has enough large positions. Therefore the check is necessary and sufficient. QED.
Computing all takes by directly applying each interval to its covered positions. This is fine because the input guarantees bound the total and , so total is also bounded.
The DP has states and transitions per state.
Overall per test case:
with memory.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const int NEG = -1000000000;
while (T--) {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), freq(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
freq[a[i]]++;
}
vector<int> b(n + 1);
iota(b.begin(), b.end(), 0);
for (int qi = 0; qi < m; qi++) {
int l, r;
cin >> l >> r;
for (int i = l; i <= r; i++) b[i] = min(b[i], l);
}
int W = n + 1;
auto id = [W](int i, int s) { return i * W + s; };
vector<array<int, 2>> dp(W * W, array<int, 2>{NEG, NEG});
vector<array<int, 2>> pref(W * W, array<int, 2>{NEG, NEG});
dp[id(0, 0)][0] = dp[id(0, 0)][1] = 0;
pref[id(0, 0)][0] = pref[id(0, 0)][1] = 0;
for (int i = 1; i <= n; i++) {
for (int s = 0; s <= n; s++) {
for (int c = 0; c < 2; c++) {
int best = NEG;
int ps = s - (c == 0);
if (ps >= 0) {
int same = pref[id(i - 1, ps)][c];
if (same > NEG / 2) best = max(best, same + (c == 1));
int other = pref[id(b[i] - 1, ps)][c ^ 1];
if (other > NEG / 2) best = max(best, other + (c == 1));
}
dp[id(i, s)][c] = best;
pref[id(i, s)][c] = max(pref[id(i - 1, s)][c], best);
}
}
}
string ans;
int less = 0;
for (int x = 1; x <= n; x++) {
int greater = n - less - freq[x];
int can = max(pref[id(n, less)][0], pref[id(n, less)][1]);
ans.push_back(can >= greater ? '1' : '0');
less += freq[x];
}
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const int NEG = -1000000000;
while (T--) {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), freq(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
freq[a[i]]++;
}
vector<int> b(n + 1);
iota(b.begin(), b.end(), 0);
for (int qi = 0; qi < m; qi++) {
int l, r;
cin >> l >> r;
for (int i = l; i <= r; i++) b[i] = min(b[i], l);
}
int W = n + 1;
auto id = [W](int i, int s) { return i * W + s; };
vector<array<int, 2>> dp(W * W, array<int, 2>{NEG, NEG});
vector<array<int, 2>> pref(W * W, array<int, 2>{NEG, NEG});
dp[id(0, 0)][0] = dp[id(0, 0)][1] = 0;
pref[id(0, 0)][0] = pref[id(0, 0)][1] = 0;
for (int i = 1; i <= n; i++) {
for (int s = 0; s <= n; s++) {
for (int c = 0; c < 2; c++) {
int best = NEG;
int ps = s - (c == 0);
if (ps >= 0) {
int same = pref[id(i - 1, ps)][c];
if (same > NEG / 2) best = max(best, same + (c == 1));
int other = pref[id(b[i] - 1, ps)][c ^ 1];
if (other > NEG / 2) best = max(best, other + (c == 1));
}
dp[id(i, s)][c] = best;
pref[id(i, s)][c] = max(pref[id(i - 1, s)][c], best);
}
}
}
string ans;
int less = 0;
for (int x = 1; x <= n; x++) {
int greater = n - less - freq[x];
int can = max(pref[id(n, less)][0], pref[id(n, less)][1]);
ans.push_back(can >= greater ? '1' : '0');
less += freq[x];
}
cout << ans << '\n';
}
}