Weird Sum

标准输出

埃戈尔有一张大小的桌子n×mn×m,行号从11到nn以及编号为11到mm。每个单元格都有一个颜色,该颜色可以表示为11到105105.

让我们表示位于rr-第四行和cc-第四栏(r,c)(r,c)。我们定义曼哈顿距离两个细胞之间(r1,c1)(r1,c1)和(r2,c2)(r2,c2)作为它们之间最短路径的长度,路径中的每个连续单元必须有一个共同的边。路径可以通过任何颜色的单元格。例如,在表中3×43×4曼哈顿之间的距离(1,2)(1,2)和(3,3)(3,3)是33,最短的路径之一是:(1,2)→(2,2)→(2,3)→(3,3)(1,2)→(2,2)→(2,3)→(3,3).

埃戈尔决定计算相同颜色的每一对细胞之间曼哈顿距离的总和。帮他算这笔钱。

输入

第一行包含两个整数。nn和mm (1≤n≤m1≤n≤m, n⋅m≤100000n⋅m≤100000)-表中的行数和列数。

下一个nn行描述表的一行。这个ii-第四行包含mm整数ci1,ci2,…,cimci1,ci2,…,cim (1≤cij≤1000001≤cij≤100000)中单元格的颜色。ii-第四排

输出量

打印一个整数--相同颜色的每个单元格之间曼哈顿距离之和。

input

Copy

2 3
1 2 3
3 2 1

output

Copy

7

input

Copy

3 4
1 1 2 2
2 1 1 2
2 2 1 1

output

Copy

76

input

Copy

4 4
1 1 2 3
2 1 1 2
3 1 2 1
1 1 2 1

output

Copy

129

 题解

我们注意到细胞间的曼哈顿距离(r1,c1)(r1,c1)和(r2,c2)(r2,c2)等于|r1−r2|+|c1−c2||r1−r2|+|c1−c2|。对于每一种颜色,我们将组成一个所有单元格的列表。(r0,c0),…,(rk−1,ck−1)(r0,c0),…,(rk−1,ck−1)对于此颜色,计算此颜色的目标和,并总结所有颜色的答案。之和相等:

∑i=0k−1∑j=i+1k−1|ri−rj|+|ci−cj|=(∑i=0k−1∑j=i+1k−1|ri−rj|)+(∑i=0k−1∑j=i+1k−1|ci−cj|)∑i=0k−1∑j=i+1k−1|ri−rj|+|ci−cj|=(∑i=0k−1∑j=i+1k−1|ri−rj|)+(∑i=0k−1∑j=i+1k−1|ci−cj|)

我们将计算第一个和,第二个和是相似的。让一个数组ss等于rr,但按顺序排列。然后:

∑i=0k−1∑j=i+1k−1|ri−rj|=∑i=0k−1∑j=i+1k−1sj−si=(∑i=0k−1∑j=i+1k−1sj)+(∑i=0k−1∑j=i+1k−1−si)∑i=0k−1∑j=i+1k−1|ri−rj|=∑i=0k−1∑j=i+1k−1sj−si=(∑i=0k−1∑j=i+1k−1sj)+(∑i=0k−1∑j=i+1k−1−si)

价值sjsj发生在第一个双和中。jj时间,价值−si−si发生在第二个和中。k−1−ik−1−i时代。然后,该值等于:

∑j=0k−1jsj+∑i=0k−1−(k−1−i)si=∑i=0k−1(2i+1−k)si∑j=0k−1jsj+∑i=0k−1−(k−1−i)si=∑i=0k−1(2i+1−k)si

最后一次和可以在O(k)O(k),排序数组的时间复杂性是O(k原木k)O(k原木⁡k)。总体的复杂性是O(nm原木(nm))O(nm原木⁡(nm))。我们还可以通过将单元格按正确的顺序添加到列表中来对坐标数组进行排序。这会产生一个O(nm)O(nm)解决办法

#include <bits/stdc++.h>

using namespace std;


const int maxn = 1e6 + 10; 

long long int  ans,len; 
int n , m;

vector<int> mp[maxn];
vector<int> rr[maxn], cc[maxn];
 
int main ()
{
    //找两个细胞间最短路径 
    cin >> n >> m ;
    for ( int i = 1 ; i <= n ; i++ ) 
    {
        mp[i].push_back(0);//压入 
        for ( int j = 1 ; j <= m ; j++ )
        {
            int x ; 
			cin >> x;
            rr[x].push_back(i);
            mp[i].push_back(x);
        }
    }
    for ( int j = 1 ; j <= m ; j++ )
    {
        for ( int i = 1 ; i <= n ; i++ )
        {
            int x = mp[i][j];
            cc[x].push_back(j);
        }
    }
    ans = 0;
    for ( int i = 1 ; i <= 100000 ; i++ )
    {
        if ( rr[i].size() > 1 )
        {
            for ( int j = 1 ; j < rr[i].size() ; j++ )
            {
                 len = rr[i][j] - rr[i][j-1];
                ans += 1ll * (rr[i].size() - j ) * len * j;
            }
        }
        if ( cc[i].size() > 1 )
        {
            for ( int j = 1 ; j < cc[i].size() ; j++ )
            {
                 len = cc[i][j] - cc[i][j-1];
                 ans += 1 * (cc[i].size() - j) * len * j;
            }
        }
    }
    cout << ans << endl;
    return 0;
}	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
		
			
		
		
	}
	

	
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值