Egor has a table of size n×mn×m, with lines numbered from 11 to nn and columns numbered from 11 to mm. Each cell has a color that can be presented as an integer from 11 to 105105.
Let us denote the cell that lies in the intersection of the rr-th row and the cc-th column as (r,c)(r,c). We define the manhattan distance between two cells (r1,c1)(r1,c1) and (r2,c2)(r2,c2) as the length of a shortest path between them where each consecutive cells in the path must have a common side. The path can go through cells of any color. For example, in the table 3×43×4 the manhattan distance between (1,2)(1,2) and (3,3)(3,3) is 33, one of the shortest paths is the following: (1,2)→(2,2)→(2,3)→(3,3)(1,2)→(2,2)→(2,3)→(3,3).
Egor decided to calculate the sum of manhattan distances between each pair of cells of the same color. Help him to calculate this sum.
Input
The first line contains two integers nn and mm (1≤n≤m1≤n≤m, n⋅m≤100000n⋅m≤100000) — number of rows and columns in the table.
Each of next nn lines describes a row of the table. The ii-th line contains mm integers ci1,ci2,…,cimci1,ci2,…,cim (1≤cij≤1000001≤cij≤100000) — colors of cells in the ii-th row.
Output
Print one integer — the the sum of manhattan distances between each pair of cells of the same color.
Examples
input
Copy
2 3 1 2 3 3 2 1
output
Copy
7
题意:给你一个nXm的矩阵,每个矩阵里有一个数,让你求所有相同的数每对之间的距离的总和。
我们先把所有数的坐标都存在一个vector<pii> a里。
对于x这个数,假设他所在的所有坐标是:
我们要计算的就是:
因为横坐标和纵坐标是一样的,所以我们考虑一个坐标就可以了
假设考虑横坐标的话,我们为了方便计算先把r从小到大排序形成一个新的数组s,我们需要算的柿子化简得到的就是
然后我们举个例子展开就可以找到规律:
sj出现了j次,si出现了(k-1-i)次,而且i和j的范围是一样的,我们可以把他看做一个数
然后我们就化简为:
然后我们就列举直接加就可以啦~
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<unordered_map>
#define int long long
#define lowbit(x) x&(-x)
#define PI 3.1415926535
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int gcd(int a,int b){
return b>0 ? gcd(b,a%b):a;
}
const int N=1e5+10;
int n,m,ans;
vector<pii> a[N];
void sove(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
a[x].push_back({i,j});
}
}
for(int i=1;i<=1e5;i++){
if(a[i].size() <=1)continue;
int len=a[i].size() ;
sort(a[i].begin() ,a[i].end() ,[&](pii p,pii q){//我在写的时候不知道怎么写排序这一块,就参考了dalao的代码
return p.first<q.first;
});
for(int j=0;j<len;j++){
ans+=(2*j-len+1)*a[i][j].first;
}
sort(a[i].begin() ,a[i].end() ,[&](pii p,pii q){
return p.second<q.second;
});
for(int j=0;j<len;j++){
ans+=(2*j-len+1)*a[i][j].second;
}
}
cout<<ans;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie() ,cout.tie() ;
int t=1;
//cin>>t;
while(t--){
sove();
}
return 0;
}