B. Polo the Penguin and Matrix

https://codeforces.com/contest/289/problem/B

题意:给定n * m的矩阵,还有一个数d,现可执行操作,每次操作可任选一个数将其±d,问最少操作多少次可以让矩阵中所有的数相等?或者输出-1表示无解。

思路:将数存到一维数组中并升序排序,做差分,如果存在某个差值不为d的整数倍,则无解。有解后,构造数组left和right,对于下标i,left[i]和right[i]分别表示将所有的数变为位置i上的数时,需要操作多少次。求出数组后,一次遍历取最优解即可。

总结:在更新left和right的时候没一次考虑清楚。更新left[i]时,首先加上left[i - 1],其次考虑i前面有多少个数,将这个数的数量 * 当前的差分值才能得到当前位置正确的操作数,这个思路对于right同理。 这个应该算,模拟题?感觉有点像暴力。

inline void solve(){
    int n, m, d;
    cin >> n >> m >> d;

    n = n * m;
    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }

    sort(a.begin(), a.end());
    vector<int> b;
    b.reserve(n);
    b.push_back(0);
    for (int i = 1; i < n; ++i) {
        b.push_back(a[i] - a[i - 1]);
        if (b.back() % d != 0) {
            cout << -1;
            return;
        }
        b.back() /= d;
    }

    vector<int> left(n + 1), right(n + 1);
    for (int i = 1; i < n; ++i) {
        left[i] = left[i - 1] + b[i] * i;
    }
    for (int i = n - 1; i > 0; --i) {
        right[i - 1] = right[i] + (b[i] * (n - i));
    }

    int ans = INF;
    for (int i = 0; i < n; ++i){
        ans = min(ans, left[i] + right[i]);
    }

    cout << ans << '\n';
}
posted @ 2025-03-12 10:36  _Yxc  阅读(13)  评论(0)    收藏  举报