ARC163B题解
:把代码块的语言改成了 c++。
题意简述
给一个长度为 的序列 ,你可以进行若干次操作:
- 选择一个整数 满足 ,将 加上或减去 。
求最少需要多少步,使得至少有 个整数 满足 ,。
解法
可以发现一个性质,只改变 的值是最优的。
证明
设 的值为 ,如果它要包含的区间的最小值为 (这里,,因为如果 , 可以不做改变),则改变 只需 步。
而如果改变的不是 ,仅仅是将 改成大于等于 的数就要花 步了,如果还有其它点的值 满足 ,那步数一定大于 步。
改变 同理。
综上可得,只改变 的值是最优的。
再配一张图理解一下(其中,红色的点分别表示 ,红线表示 移动的步数,蓝线为其它点移动的步数,可以看出红线总长比蓝线总长短)

还有一个很好证明性质,包含的区间一定是按顺序(从大到小、从小到大都可以)排序中一个连续的子序列。
算法简述
对后 个点从小到大排序(当然,从大到小也可以),依次枚举长度为 的区间(即左端点在 的长度为 的区间)。求出将 改变成小于等于左端点的值, 改变成大于等于右端点的值最少需要的步数即可。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,a1,a2,b[200010],ans=0x7fffffff;
bool cmp(int x,int y){
return x<y;
}
int main(){
scanf("%d%d",&n,&m);
scanf("%d%d",&a1,&a2);//A1,A2分开读
n-=2;
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
sort(b+1,b+n+1,cmp);
for(int i=1;i<=n-m+1;i++) ans=min(ans,max(a1-b[i],0)+max(b[i+m-1]-a2,0));
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号