【前缀和】Matrix Distance
https://codeforces.com/gym/104857/problem/E
本来想卡常,后来发现O(m2n2)怎么看都感觉不太对劲哈哈哈哈
所以查了一下,发现曼哈顿距离可以用距离贡献度来看
前缀和计算曼哈顿距离
xi右侧的坐标数量为n-i,那么这些坐标与xi的距离之和为:右侧坐标的累加和减去xi乘以(n-i)。
我们可以通过维护一个前缀和数组来有效计算这些累加和,从而避免对每个坐标进行双重循环的计算。
具体步骤如下:
排序坐标:先将所有坐标按照从小到大排序。
计算前缀和:遍历坐标,计算到当前坐标为止的所有坐标的累加值,存储在前缀和数组中。
计算每个坐标的贡献:
对于每个坐标xi,其对总距离的贡献可以通过前缀和快速得到。具体来说:
对于左侧的坐标,使用前缀和直接获得x1到xi-1的和。
对于右侧的坐标,使用总和减去前缀和得到xi+1到xn的和。
累加计算结果:将所有坐标的贡献累加起来,得到总的曼哈顿距离。
这种方法的时间复杂度主要是排序的O(n log n)和单遍历的O(n),因此总体效率是O(n log n),这比暴力方法的O(n^2)要有效得多。
然后出现了TLE,优化了一下
ll calculateDistanceContributions(const vector<int>& positions) { int size = positions.size(); ll sum = 0, totalSum = 0; for (int i = 0; i < size; ++i) { totalSum += (ll)positions[i] * i - sum; sum += positions[i]; } return totalSum * 2; // Multiply by 2 to count both sides }
还有就是读入的时候需要
ios::sync_with_stdio(false); cin.tie(nullptr);