提高组杂题训练
分类讨论。为了使和最大化,需要序列中的每个元素都为最大的元素。
若 \(n \ge 4\),设序列中的最大元素的位置为 \(x\) ,那么必有 $x-1 \ge 2 $ 或 \(n-x\ge2\) ,所以只需要选 \(n-1\) 和\(n\) 两个元素操作两次变为0,对\(x\sim n\) 赋值,再选 \(1\) 和\(2\) 两个元素操作两次变为0,对\(1\sim x-1\) 赋值
若 \(n=2\) ,两种情况。\(\left|a_i-b_i\right|\) 或不操作,取 \(\max\) 即可。
若 \(n=3\) ,若最大元素是 \(a_1\) 或 \(a_3\) ,还是可以将每个元素都变成最大。若最大元素为\(a_2\),有两种情况。
若选择 \((1,2)\) 操作,每个数的最大值为 \(\max(a_3,\left|a_1-a_2\right|)\) ;若选择 \((2,3)\) 操作,每个数的最大值为 \(\max(a_1,\left|a_3-a_2\right|)\) ,最后取最大值即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,a[maxn],T,ans;
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
if(n==1){
cout<<a[1]<<'\n';
continue;
}
else if(n==2){
cout<<max(2*abs(a[1]-a[2]),a[1]+a[2])<<'\n';
continue;
}
else if(n==3){
cout<<max({3*abs(a[1]-a[2]),3*abs(a[3]-a[2]),3*a[1],3*a[3],a[1]+a[2]+a[3]})<<'\n';
continue;
}
else{
sort(a+1,a+1+n);
cout<<a[n]*n<<'\n';
continue;
}
}
}
你说得对但是我最开始真的觉得很像贪心被硬控40min+
记 \(b\) 数组为 \(a\) 的前缀和,一次操作就是在 \(b\) 中任选一些数字 \(\pm1\) 。
手模一下发现 \(b\) 元素全0 是 \(a\) 元素全0 的充要条件。
求前缀和数组中的极值,相减即可。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+10;
int T,n,a[maxn];
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++) a[i]=a[i-1]+a[i];
int mn=0,mx=0;
for(int i=1;i<=n;i++) mn=min(mn,a[i]),mx=max(mx,a[i]);
cout<<mx-mn<<'\n';
}
}