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 subarray, do not try to construct the whole best array . The prefix maximum condition makes each position almost independent once you know the prefix maximum of up to that position.
Suppose in the subarray ending-prefix at position , the current prefix maximum is . If creates a new strict prefix maximum, then is forced to equal . Otherwise, can be any value at most .
So position contributes to a subarray exactly when either and is the strict maximum on , or and is not a strict maximum on .
The right endpoint only multiplies things: if position is good for a left endpoint , then it is good for all , giving a factor of . Now the problem is: for each , count valid .
Let be the last index before with . Then is a strict prefix maximum exactly for . For the non-strict case, you need a previous value in at least ; equivalently , where is the last index before with . Combine these two ranges carefully. That is the whole trick; the rest is just monotonic stacks plus offline queries.
First, shrink the scary definition until it stops acting tough.
For one fixed pair of arrays , let
The condition on is exactly that the prefix maximum sequence of is .
At position :
So for a fixed subarray , position can be matched with iff one of these happens:
That is the key deconstruction. There is no global DP over . Each position either can be made equal to or it cannot. Nice.
Turning the double sum around
Instead of iterating over every subarray, count how many subarrays each position contributes to.
A contribution of position depends only on the left endpoint and the prefix . Once and are fixed, every right endpoint includes that same contribution.
So if is the number of left endpoints for which position is matchable, then the answer is
Now we only need to compute each .
When is a strict prefix maximum?
Let
or if no such index exists.
Then is a strict maximum of exactly when no earlier element in that range is . That means
So the strict-prefix-maximum left endpoints are
There are of them.
If , all of those left endpoints are valid.
If , none of those strict endpoints are valid, because is forced to equal . No negotiating with the prefix maximum police.
The non-strict case
Now consider left endpoints where is not a strict prefix maximum. These are exactly
For these, the current prefix maximum is
and position can match iff
Because is not strict here, . If , then automatically , so every works.
If , then we need some previous element in that is at least .
Define
or if no such index exists.
Then there is such an element in exactly when
So the number of valid non-strict left endpoints is:
Notice that when , any index with also has , so . Good, no hidden overcount.
Final formula
For each position :
So
\begin{cases} i, & b_i=a_i,\\ p_i, & b_i<a_i,\\ q_i, & b_i>a_i. \end{cases}$$ Why does $b_i=a_i$ become $i$? Because the strict part gives $i-p_i$, and the non-strict part gives $p_i$, so every left endpoint works. If $b_i=a_i$, just set $z_i=a_i; of course it fits. Then add $$c_i(n-i+1)$$ to the answer. **Computing $p_i$ and $q_i$** We need previous indices with values at least some threshold. For $p_i$, the threshold is $a_i$. For $q_i$, the threshold is $b_i$. Since $a_i,b_i\le 2n$, this can be done with a Fenwick tree over values. Sweep $i$ from left to right. The Fenwick tree stores, for each value $v$, the maximum index seen so far with $a_j=v$. To query the maximum previous index with value at least $T$, query the suffix $[T,2n]$. A standard Fenwick tree does prefix queries, so flip the value: $$rev(v)=V-v+1,$$ where $V=2n+2$. Then values $\ge T$ become reversed indices $\le rev(T)$, so a prefix maximum query gives exactly what we want. After answering queries for position $i$, insert $a_i$ with value $i$. Complexity: $O(n\log n)$ per test case, and $O(n)$ memory. With total $n\le 2\cdot 10^5$, this is comfortably AC.#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct FenwickMax {
int n;
vector<int> bit;
FenwickMax(int n = 0) { init(n); }
void init(int n_) {
n = n_;
bit.assign(n + 1, 0);
}
void update(int idx, int val) {
for (; idx <= n; idx += idx & -idx) bit[idx] = max(bit[idx], val);
}
int query(int idx) const {
int res = 0;
for (; idx > 0; idx -= idx & -idx) res = max(res, bit[idx]);
return res;
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
int V = 2 * n + 2;
FenwickMax fw(V + 2);
ll ans = 0;
for (int i = 1; i <= n; i++) {
auto rev = [&](int x) {
return V - x + 1;
};
int p = fw.query(rev(a[i]));
int c;
if (b[i] == a[i]) {
c = i;
} else if (b[i] < a[i]) {
c = p;
} else {
int q = fw.query(rev(b[i]));
c = q;
}
ans += 1LL * c * (n - i + 1);
fw.update(rev(a[i]), i);
}
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);
}
struct FenwickMax {
int n;
vector<int> bit;
FenwickMax(int n = 0) { init(n); }
void init(int n_) {
n = n_;
bit.assign(n + 1, 0);
}
void update(int idx, int val) {
for (; idx <= n; idx += idx & -idx) bit[idx] = max(bit[idx], val);
}
int query(int idx) const {
int res = 0;
for (; idx > 0; idx -= idx & -idx) res = max(res, bit[idx]);
return res;
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
int V = 2 * n + 2;
FenwickMax fw(V + 2);
ll ans = 0;
for (int i = 1; i <= n; i++) {
auto rev = [&](int x) {
return V - x + 1;
};
int p = fw.query(rev(a[i]));
int c;
if (b[i] == a[i]) {
c = i;
} else if (b[i] < a[i]) {
c = p;
} else {
int q = fw.query(rev(b[i]));
c = q;
}
ans += 1LL * c * (n - i + 1);
fw.update(rev(a[i]), i);
}
cout << ans << '\n';
}
return 0;
}