Egor有一个大小为n×m的表,行从1到n编号,列从1到m编号。每个单元格有一个颜色,可以表示为1到105的整数。
设第r行和第c列交点的单元格为(r,c)我们定义两个单元(r1,c1)和(r2,c2)之间的曼哈顿距离为它们之间的最短路径长度,其中路径上的每个连续单元必须有公共边。路径可以通过任何颜色的单元格。例如,在表3×4中(1,2)与(3,3)之间的曼哈顿距离为3,其中一条最短路径为:(1,2)→(2,2)→(2,3)→(3,3)。
Egor决定计算相同颜色的每对细胞之间的曼哈顿距离之和。帮他算一下这笔款子。
输入
第一行包含2个整数n和m(1≤n≤m, n⋅m≤100000)-表中的行数和列数。
接下来的n行描述表中的一行。第i行包含m个整数ci1,ci2,…,cim(1≤cij≤100000)-第i行单元格的颜色。
输出
打印一个整数-相同颜色的每对单元格之间的曼哈顿距离的和。
例子
inputCopy
2 3
1 2 3
3 2 1
outputCopy
7
inputCopy
3 4
112 22
2 1 1 2
2 2 1 1
outputCopy
76
inputCopy
4 4
1 1 2 3
2 1 1 2
3 1 2 1
111 121
outputCopy
129
请注意
在第一个样本中,有三对相同颜色的细胞:在细胞(1,1)和(2,3)中,在细胞(1,2)和(2,2)中,在细胞(1,3)和(2,1)中。它们之间的曼哈顿距离是3 1和3,和是7。
solve1:把x,和y分别计算。因为每两两之间都会计算一次 所以分开考虑不影响结果。分别对x,y排序后计算每一段会被计算几次
就可以O(n)计算完。
还没有想清楚solve1的计算公式咋推的。。。。
solve2:对于x或y轴求一次的公式推导: (A2-A1)+(A3-A1)+(A4-A1)+…+(An-A1)
+(A3-A2)+(A4-A2)+…+(An-A2)
… … …+(An-An-1)
==A2+2A3+3A4+…+(n-1)An - (n-1)A1-(n-2)A2-…-(n-(n-1))An-1
==(1-n)A1+(3-n)A2+(5-N)A3+…+(2i-1-n)Ai+…+(n-1)An
==求和((2i-1-n)Ai) i=1,2,3,4,…n 题中遍历i时由于从0开始,
故为 2*(i+1)- n+1=2i-n+1
solve2倒是很好推。。。。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;
const int N=1e6+10,M=1e3+10,mod=1e9+7;
int m,t,n,f;
int st[N];
int a[N];
vector<int>x[N],y[N];
void solve2(){
cin>>n>>m;
int len=0,w=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>w;
len=max(len,w);
x[w].push_back(i);
y[w].push_back(j);
}
int s=0;
for(int k=1;k<=len;k++){
sort(x[k].begin(),x[k].end());
sort(y[k].begin(),y[k].end());
int l=x[k].size();
for(int i=0;i<l;i++){
s+=(2*i-l+1)*(x[k][i]+y[k][i]);
}
}
cout<<s<<endl;
}
void solve(){
cin>>n>>m;
int w;
ll sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) {
cin >> w;//该点的值
x[w].push_back(i);//该点的x坐标
y[w].push_back(j);//y坐标
}
for(int i=1;i<=100000;i++)//横纵坐标从小到大排序
sort(x[i].begin(),x[i].end()),sort(y[i].begin(),y[i].end());
ll ans=0;
for(int i=1;i<=100000;i++){
int len=x[i].size();
if(x[i].size()==0) continue;//值为i的点个数为0
ll sumx=0,sumy=0;
for(int j=0;j<len;j++){
sumx+=(x[i][j]-x[i][j-1])*j;
cout<<" sumx="<<sumx<<endl;
sum+=sumx;
}
len=y[i].size();
for(int j=1;j<len;j++){
sumy+=(y[i][j]-y[i][j-1])*j;
cout<<" sumy="<<sumy<<endl;
sum+=sumy;
}
}
cout<<sum<<endl;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);
solve2();
return 0;
}