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.
Think of the coloring condition as saying something about each color class. If two chosen elements of the same color formed an inversion, that edge would have equal-colored endpoints, which is illegal.
So a good subsequence is exactly one that can be split into two nondecreasing subsequences. This is less about graph coloring and more about chain covers in disguise.
A sequence can be split into two nondecreasing subsequences iff it has no strictly decreasing subsequence of length . One direction is obvious by pigeonhole; the other is the usual greedy/patience-sorting fact.
While scanning left to right, a valid subsequence only needs to remember the best decreasing subsequence of length and length inside it. Store them as two thresholds : is the minimum possible last value of a decreasing subsequence of length , and is the minimum possible last value of a decreasing subsequence of length .
For a new value : if , it starts/improves a length- decreasing subsequence, so set ; else if , it starts/improves a length- decreasing subsequence after some larger previous value, so set ; otherwise it changes nothing. The only forbidden case is when taking would extend an existing length- decreasing subsequence into length .
A subsequence is good iff its inversion graph is bipartite. That sounds graphy, but the clean way in is much simpler.
If two indices have the same color, they are not allowed to be an inversion. So within each color, values must appear in nondecreasing order. Therefore:
A subsequence is good iff it can be partitioned into two nondecreasing subsequences.
By the standard chain-cover fact, that is equivalent to:
The subsequence has no strictly decreasing subsequence of length .
One direction is immediate: if you split the sequence into two nondecreasing parts, then any strictly decreasing triple would need three different colors. Bad news, there are only two colors.
The other direction is the usual greedy/patience-sorting argument: if the longest strictly decreasing subsequence has length at most , then two nondecreasing piles are enough.
So now the problem is: count subsequences of that avoid a pattern
No graph coloring needed anymore. The graph was wearing a fake mustache.
State
Scan the original array from left to right and build subsequences by deciding whether to take each element.
For a currently built subsequence with no decreasing triple, define:
If such a decreasing subsequence does not exist, use sentinel value .
The empty subsequence starts at:
Smaller ending values are more dangerous: a future value extends a decreasing pair exactly when that pair ends at a value greater than .
Transition
Suppose the next array value is .
For every state , we can always skip .
If we take :
DP
Let be the number of ways to obtain state after processing a prefix.
Initialize:
For each value , copy all states for the skip option, then add the valid take transitions.
At the end, every state is a valid good subsequence, including the empty one, so the answer is:
Correctness Proof
A subsequence is good iff it can be split into two nondecreasing subsequences: same-colored elements cannot form inversions, and two nondecreasing parts can be colored red/blue directly.
A sequence can be split into two nondecreasing subsequences iff it has no strictly decreasing subsequence of length . A decreasing triple needs three different nondecreasing parts, while the greedy pile process uses at most two piles exactly when no third decreasing layer exists.
The DP invariant is: after processing a prefix, counts exactly the valid subsequences whose best length- and length- decreasing-subsequence ending values are .
The initial empty subsequence satisfies this. Skipping preserves the state. Taking is rejected exactly when it creates a decreasing triple, and otherwise updates the best length- ending value precisely when . Therefore every valid subsequence is counted once, and no invalid subsequence is counted.
So the DP counts exactly the good subsequences.
Complexity
There are states and elements, so the time complexity is with memory. For , that is comfortably fine.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MOD = 1000000007;
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
int S = n + 1;
vector<vector<int>> dp(S + 2, vector<int>(S + 2, 0));
dp[S][S] = 1;
for (int v : a) {
auto ndp = dp; // skip v
for (int x = 1; x <= S; x++) {
for (int y = 1; y <= S; y++) {
int cur = dp[x][y];
if (!cur) continue;
if (y > v) {
continue; // would create a decreasing subsequence of length 3
}
int nx = x, ny = y;
if (x > v) ny = v;
ndp[nx][ny] += cur;
if (ndp[nx][ny] >= MOD) ndp[nx][ny] -= MOD;
}
}
dp.swap(ndp);
}
int ans = 0;
for (int x = 1; x <= S; x++) {
for (int y = 1; y <= S; y++) {
ans += dp[x][y];
if (ans >= MOD) ans -= MOD;
}
}
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
const int MOD = 1000000007;
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
for (int &x : a) cin >> x;
int S = n + 1;
vector<vector<int>> dp(S + 2, vector<int>(S + 2, 0));
dp[S][S] = 1;
for (int v : a) {
auto ndp = dp; // skip v
for (int x = 1; x <= S; x++) {
for (int y = 1; y <= S; y++) {
int cur = dp[x][y];
if (!cur) continue;
if (y > v) {
continue; // would create a decreasing subsequence of length 3
}
int nx = x, ny = y;
if (x > v) ny = v;
ndp[nx][ny] += cur;
if (ndp[nx][ny] >= MOD) ndp[nx][ny] -= MOD;
}
}
dp.swap(ndp);
}
int ans = 0;
for (int x = 1; x <= S; x++) {
for (int y = 1; y <= S; y++) {
ans += dp[x][y];
if (ans >= MOD) ans -= MOD;
}
}
cout << ans << '\n';
}
return 0;
}