去年新生赛预选题目 赛时没做出来
最小代价其实就是全部变到中位数 但是这样需要排序 因为本身数组不一定有序 那么此时就陷入僵局了
但是题目给了一个条件特别重要 1 <= a[i] <= 100
也就是说我最终要变到的中位数的值一定属于[1,100]
所以我可以预先处理a[i]的前n项全部变到[1,100]之间的任意一个值所需要的总魔力值 用数组b[i][j]记录,i是目标魔力值 j是数组的项数 这样就转变成了一个前缀和问题 我只需要每次枚举1~100 每次更新ans = ( ans, b[i][r] - b[i][l - 1] ) 即可获得最终答案

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[110][N];
int main () {
  ios::sync_with_stdio(0), cin.tie(0);
  int n, m;cin >> n >> m;
  for (int i = 1;i <= n; ++ i) cin >> a[i];
  for (int i = 1;i <= 100; ++ i) {
    for (int j = 1;j <= n; ++ j) {
      // 将前j项变化到i所需花费的魔力值
      b[i][j] = b[i][j - 1] + abs(a[j] - i);
    }
  }
  while (m--) {
    int l, r;cin >> l >> r;
    int ans = 2e9;
    for (int i = 1;i <= 100; ++ i) {
      ans = min(ans, b[i][r] - b[i][l - 1]);
    }
    cout << ans << '\n';
  }
}

对于这样的前缀和 需要多加注意