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';
}

浙公网安备 33010602011771号