E - Sowing Stones Editorial by en_translator
This problem can be solved by determining if one can reach the state where every cell has one stone, and finding the minimum number of operations required if possible.
Condition that every cell can end up having one stone
First, \(\sum_{i=1}^{M}A_i=N\) is necessary. We assume this.
Then the necessary and sufficient condition is that cells \(1,2,\ldots,i\) have a total of \(i\) or more stones.
This can be understood like this: if we assign the numbers \(1,2,\ldots,N\) to each stone in the cell in the leftmost cell to the rightmost in order, then every stone can be moved to the cell with the number assigned to the stone.
Checking the condition for all \(i\) is a bit difficult because \(N\) can be up to \(2 \times 10^9\), but there are only \(M\) indices \(i\) such that the total number of stones in cells \(1,2,\ldots,i\) changes, namely indices \(X_1,X_2,\ldots,X_M\), so it is sufficient to scan only \(i=X_1-1,X_2-1,\ldots,X_M-1\) \((1 \leq i \leq M)\). Also, by sorting as \(X_1 < X_2 \ldots <X_M\) to facilitate finding the total number of stones in cells up to \(i\), and incrementally calculating the cumulative sum, the whole process except for sorting can be done in \(O(M)\) time.
How to find the minimum number of operations required
Consider the total sum of indices of cells where the stones are located at. Every operation moves a stone from cell \(i\) to \((i+1)\), incrementing the sum by one. By checking the condition above beforehand, we can simply focus on the delta to find the number of operations.
Thus, the minimum number of operations is \(\frac{N(N+1)}{2}-\displaystyle \sum_{i=1}^{M}X_i \times A_i \).
The computational complexity is \(O(M\log M)\), where sorting is the bottleneck.
Sample code (C++):
#include <bits/stdc++.h>
using namespace std;
int main() {
long long n;
int m;
cin >> n >> m;
vector<pair<int, long long>> xa(m);
for (int i = 0; i < m; ++i) {
cin >> xa[i].first;
}
for (int i = 0; i < m; ++i) {
cin >> xa[i].second;
}
sort(xa.begin(), xa.end());
long long sum = 0, sum_idx = 0;
for (int i = 0; i < m; ++i) {
if (sum < xa[i].first - 1) {
cout << -1 << endl;
return 0;
}
sum += xa[i].second;
sum_idx += xa[i].second * xa[i].first;
}
if (sum != n) {
cout << -1 << endl;
return 0;
}
cout << n * (n + 1) / 2 - sum_idx << endl;
}
posted:
last update: