Problem Author: | De3b0o |
Prepared by: | De3b0o |
Edited by: | Hasan Saleh (MathModel) |
Solution
Fact: if we make an operation on an index , it's always optimal to choose x = \max(a_1,a_2,...,a_{i-1}).
Proof:
There are two cases:
If initially a_i \le \max(a_1,a_2,...,a_{i-1}), then choosing x = \max(a_1,a_2,...,a_{i-1}) increases the mog value by .
Otherwise if a_i > \max(a_1,a_2,...,a_{i-1}), by choosing x = \max(a_1,a_2,...,a_{i-1}) the mog value for prefix stays the same but it could increase for the entire array by allowing new maximums after .
Algorithm:
Traverse the array from left to right, keeping track of:
: the current maximum seen so far.
: the second largest value before the current maximum.
: the current mog value (number of times a new maximum occurs up to this point).
: the index of the latest maximum.
For each element :
If mx1 \le a_i, it is a new maximum:
Increment by .
Update mx2 = mx1 and mx1 = a_i.
Update id = i.
Otherwise if mx2 \le a_i \le mx1, it can contribute to increasing later mog values if we change a_{id} (because the only thing preventing a_i from becoming a prefix maximum is a_{id}):
Increment dp_{id} by .
Update mx2 = a_i.
After processing the array:
ans = c + \max(dp_i)
Complexity: per test case.
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll N = 2e5+9;
ll n;
ll a[N],dp[N];
void solve()
{
cin >> n;
for(int i = 1 ; n>=i ; i++)
cin >> a[i],dp[i]=0;
ll mx1 = -2e9 , mx2 = -2e9 , c = 0 , id = 0;
for(int i = 1 ; n>=i ; i++)
{
if(a[i]>=mx1)
{
c++;
mx2=mx1;
mx1=a[i];
id=i;
}
else if(a[i]>=mx2)
{
mx2=a[i];
dp[id]++;
}
}
ll ans = c+1;
if(ans==n+1)
ans--;
for(int i = 1 ; n>=i ; i++)
ans=max(ans,c+dp[i]);
cout << ans << "\n";
}
int main()
{
ll T=1;
cin >> T;
while(T--)
solve();
}