C. Weird Sum

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;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值