![](http://dsideal.obs.cn-north-1.myhuaweicloud.com/HuangHai/BlogImages/2023/02/8e9859f774149cd1dfc90c107377b745.png) ### 解题思路 首先猜想最终相等的元素`t`的范围,最终应为数组中的某个元素。 * 若`t`小于数组中所有的元素,则此时增大`t`,那么所有元素变为`t`的次数将减小,可见`t`并非最优解; * 若`t`大于数组中所有的元素,则此时减小`t`,那么所有元素变为`t`的次数将减小,可见`t`并非最优解; 可见`t`应该位于数组最大与最小值之间,下面证明最优的`t`可以取为数组中的某个元素,从而遍历数组元素即可。
如上图所示,设t为数组最大与最小值之间的一个值,若`t`不为数组中的某个元素,则设此时大于`t`的元素有`x`个,小于t的元素为`y`个。 若`x>y`,则上移一格`t`,此时操作数变化量为`-x+y<0`,将会更优; 若`x using namespace std; const int INF = 0x3f3f3f3f; const int N = 1010; int a[N]; int n, k; int res = INF; // 时间复杂度:10000*10000=1e8,C++一秒可过 /** 测试用例I: 3 2 3 6 1 答案 3 测试用例II: 4 2 2 6 11 18 答案: 4 解释: 将2调到6,需要4步。 也可以把2调到3,1步。 把6降到3,3步,共4步。 测试用例III: 5 3 2 6 11 18 14 答案: 7 解释: 将11调到14,需要3步 将18调到14,需要4步,共7步。 测试用例IV 5 3 1 2 7 8 12 答案:5 解释: 最终结果是8, 7+1=8,1步 8不需要动,0步 12-8=4,4步 共1+0+4=5步 */ int main() { cin >> n >> k; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i < n - k + 1; i++) { // 枚举起点 vector b; for (int j = i; j <= i + k - 1; j++) b.push_back(a[j]); // 将每个可用范围复制到数组b中 sort(b.begin(), b.end()); // 排序 int cnt = 0; // 变更次数 for (int j = 0; j < b.size(); j++) cnt += abs(b[b.size() / 2] - b[j]); // 枚举每个数字与中位数对比 res = min(res, cnt); // 记录最少变更次数 } printf("%d\n", res); return 0; } ```