CF1648A Weird Sum 解题报告

CF1648A. Weird Sum

给出两个整数 $n,m$,和一个 $n \times m$ 的矩阵。若该矩阵中两元素相同,$sum$ 就加上它们所在位置的曼哈顿距离。求 $sum$ 的值。

$1 \leq n \le m, n \cdot m \leq 100000$

思路

首先给出曼哈顿距离的定义式:

$$
dis_{i,j} = |x_i - x_j| + |y_i - y_j|
$$

是两个绝对值的加和,而题目中所让我们求的同种颜色的两两之间曼哈顿距离,可以表示为如下式:

$$
\sum\limits_{col_{x_i,y_i} = k} \sum\limits_{col_{x_j,y_j} = k,i\not ={j}} |x_i - x_j| + |y_i - y_j|
$$

显然,我们可以把 $x,y$ 拆开来计算,以下先考虑 $x$ 的部分如何计算,$y$ 的部分同理。

首先,我们可以把 $x_i$ 进行排序,记当前颜色有 $p$ 个点,那么 $x$ 部分的贡献可以如下表示

$$
\begin{aligned}
&\sum\limits_{i =1}^p \sum\limits_{j = 1}^{i-1} |x_j - x_i| \
= &\sum\limits_{i =1}^p \sum\limits_{j = 1}^{i-1} x_i - x_j\
= &\sum\limits_{i =1}^p (i-1)\times x_i - \sum\limits_{j = 1}^{i-1} x_j
\end{aligned}
$$

显然,这个式子里的 $(i-1)\times x_i$ 我们可以在 $\mathcal{O}(1)$ 的时间复杂度内算出,而 $\sum\limits_{j = 1}^{i-1} x_j$ 可以在一个维护前缀和的过程中算出,时间复杂度为 $\mathcal{O}(p)$.

对每种颜色做一遍上面的计算,总时间复杂度为 $\mathcal{O}(\sum p ) = \mathcal{O}(n\times m)$,可以通过本题。$y$ 的计算同理,此处不再赘述。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const int N = 1e5 + 10;

int n,m;
vector <int> c1[N],c2[N];

void solve() {
for (int i = 1;i <= 100000;++i) c1[i].clear(),c2[i].clear();
read(n,m);
for (int i = 0;i < n;++i) {
for (int j = 0;j < m;++j) {
int col;read(col);
c1[col].push_back(i);
c2[col].push_back(j);
}
}
int ans = 0;
for (int i = 1;i <= 100000;++i) {
if (c1[i].empty()) continue;
sort(c1[i].begin(),c1[i].end());
int pre = 0;
for (int j = 0;j < c1[i].size();++j) {
ans += j * c1[i][j] - pre;
pre += c1[i][j];
}
}
for (int i = 1;i <= 100000;++i) {
if (c2[i].empty()) continue;
sort(c2[i].begin(),c2[i].end());
int pre = 0;
for (int j = 0;j < c2[i].size();++j) {
ans += j * c2[i][j] - pre;
pre += c2[i][j];
}
}

printf("%lld\n",ans);
}

signed main() {
solve();
return 0;
}
作者

Doubeecat

发布于

2022-07-20

更新于

2025-09-18

许可协议