(题目传送门)
题目描述(此处简化了亿点点)
给出一个长为n的整数序列,并给这个序列进行m次操作,每次操作可以任意选择序列中一个数 ,令变成、、、这四个结果中的一个。最终希望m次操作后整个序列的极差最大。
输入格式
第一行两个整数n,m
第二行n个整数,表示序列
输出格式
共一行
一个整数,表示最大的极差
输入输出样例
输入
3 2
0 1 0
输出
6
数据范围
对于100%的数据,1<n<,0<m<11,0<<
以上是题目部分;以下是题解部分:
设当前的最大值为mx,最小值为mn。为了让极差变大,我们显然是只操作这两个数。并且一定是让mx变大,mn变小。所以我们只可能进行这四个操作:
1.
2.
3.
4.
下面我们就来考虑那种操作对答案的贡献更大:设一次操作对答案的贡献。那么这四种操作的贡献分别为:
1.。
2.。
3.。
4.。
显然有。所以不可能进行。也就意味着如果我们改变最小值,每次操作最多将答案+2。而如果改变最大值,每次操作至少可以让答案+2。所以我们只要操作最大值就可以了。下面我们考虑如何选取和操作。不难发现,当 mx>2时,进行操作更优。当 mx=2时,两种操作效果一样。当mx<2时,进行操作更优。并且当进行一次操作后必然有mx>1。所以我们只需要记录初始序列的最大值和最小值,如果最大值小于2,就先将其+2,然后不断的对最大值进行*2操作即可。
C语言:
#include<stdio.h>
long long n,m,x,maxx=0,minx=1e9;
int main() {
scanf("%lld %lld",n,m);
for(long long i=0;i<n;i++) {
scanf("%lld",x);
if(x>maxx) {
maxx=x;
}
if(x<minx) {
minx=x;
}
}
if(maxx<2) {
maxx+=2;
m--;
}
printf("%lld",((1ll*maxx)<<m)-minx);
return 0;
}
C++:
#include<iostream>
using namespace std;
long long n,m,x,maxx=0,minx=1e9;
int main() {
cin>>n>>m;
for(long long i=0;i<n;i++) {
cin>>x;
if(x>maxx) {
maxx=x;
}
if(x<minx) {
minx=x;
}
}
if(maxx<2) {
maxx+=2;
m--;
}
cout<<((1ll*maxx)<<m)-minx;
return 0;
}