CF1763C
Update on 2023.8.17:修正了一处小错误。
分析题目可知,答案至少为 \(\sum_{i=1}^{n} a_i\)。接下来考虑怎样使答案更大。
可以对 \(n\) 分成如下几类情况讨论:
- \(n=2\)
这种情况十分简单,如果选择操作最多一次,否则两次就会变为 \(0\)。用 $ \left| a_1 - a_2 \right | \times 2$ 判断是否能更新答案即可。
- \(n=3\)
这种情况较为复杂,再细分成几种情况:
-
\(a_1\) 为最大值。此时对区间 \([2,3]\) 进行两次操作,将其全部变为 \(0\),再对区间 \([1,3]\) 进行一次操作,即可将整个序列都变为 \(a_1\)。用 \(a_1 \times n\) 判断是否能更新答案即可。
-
\(a_3\) 为最大值。与情况 \(1\) 同理。
-
\(a_2\) 为最大值。选择 \([1,2]\) 或 \([2,3]\) 区间进行一次操作,再选择 \([1,3]\) 区间进行一次操作,对每次操作后的序列都求和并判断是否能更新答案。
- \(n>3\)
易证,经过若干次操作后,答案最大能更新为 $ \max {a} \times n$,读者如果感兴趣可以模拟序列 \([1,2,3,2]\) 的变换过程,体会其原理。
上代码,具体实现详见下面。
#include <iostream>
#include <cstdio>
#include <cmath>
#define int long long
using namespace std;
int n,a[1000001],ans,mx;
signed main()
{
int T;
cin >> T;
while( T -- )
{
ans = 0;
mx = 0;
cin >> n;
for( int i = 1 ; i <= n ; i ++ )
{
cin >> a[i];
ans += a[i];
mx = max( mx , a[i] );
}
if( n == 2 ) cout << max( ans , abs( a[1] - a[2] ) * 2 ) << endl;
if( n == 3 ) cout << max( ans , max( max( a[1] * 3 , a[3] * 3 ) , max( max( abs( a[1] - a[2] ) * 2 + a[3] , abs( a[3] - a[2] ) * 2 + a[1] ) , max( abs( a[1] - a[2] ) * 3 , abs( a[3] - a[2] ) * 3 )) ) ) << endl;
if( n > 3 ) cout << max( ans , mx * n ) << endl;
}
return 0;
}
还是菜。