教主要带领一群Orzer到一个雄奇地方勘察资源。
这个地方可以用一个n×m的矩阵A[i, j]来描述,而教主所在的位置则是位于矩阵的第1行第1列。
矩阵的每一个元素A[i, j]均为一个不超过n×m的正整数,描述了位于这个位置资源的类型为第A[i, j]类。教主准备选择一个子矩阵作为勘察的范围,矩阵的左上角即为教主所在的(1, 1)。若某类资源k在教主勘察的范围内恰好出现一次。或者说若教主选择了(x, y)即第x行第y列作为子矩阵的右下角,那么在这个子矩阵中只有一个A[i, j](1≤i≤x,1≤j≤y)满足A[i, j]=k,那么第k类资源则被教主认为是稀有资源。
现在问题是,对于所有的(x, y),询问若(x, y)作为子矩阵的右下角,会有多少类不同的资源被教主认为是稀有资源。
这个地方可以用一个n×m的矩阵A[i, j]来描述,而教主所在的位置则是位于矩阵的第1行第1列。
矩阵的每一个元素A[i, j]均为一个不超过n×m的正整数,描述了位于这个位置资源的类型为第A[i, j]类。教主准备选择一个子矩阵作为勘察的范围,矩阵的左上角即为教主所在的(1, 1)。若某类资源k在教主勘察的范围内恰好出现一次。或者说若教主选择了(x, y)即第x行第y列作为子矩阵的右下角,那么在这个子矩阵中只有一个A[i, j](1≤i≤x,1≤j≤y)满足A[i, j]=k,那么第k类资源则被教主认为是稀有资源。
现在问题是,对于所有的(x, y),询问若(x, y)作为子矩阵的右下角,会有多少类不同的资源被教主认为是稀有资源。
Input
输入的第一行包括两个正整数n和m,接下来n行,每行m个数字,描述了A[i, j]这个矩阵。
Output
为了照顾Vijos脑残的输出问题,设B[i, j]表示仅包含前i行与前j列的子矩阵有多少个数字恰好出现一次,那么你所要输出所有B[i, j]之和mod 19900907。
Sample Input
2 3
1 2 3
3 1 2
1 2 3
3 1 2
Sample Output
10
【样例说明】
对于右下角为(1,1)的子矩阵,仅包含数字1,所以答案为1。
对于右下角为(1,2)的子矩阵,数字1、2各出现一次,所以答案为2。
对于右下角为(1,3)的子矩阵,数字1、2、3各出现一次,所以答案为3。
对于右下角为(2,1)的子矩阵,数字1、3各出现一次,所以答案为2。
对于右下角为(2,2)的子矩阵,数字2、3各出现一次,但是数字1出现了两次,所以数字1不统计入答案,答案为2。
对于右下角为(2,3)的子矩阵,数字1、2、3均出现了两次,所以答案为0。
【数据说明】
对于10%的数据,有N,M≤10;
对于20%的数据,有N,M≤20;
对于40%的数据,有N,M≤150;
对于50%的数据,A[I, J]≤1000;
对于70%的数据,有N,M≤800;
对于100%的数据,有N,M≤1100,A[I, J] ≤N×M。
对于右下角为(1,1)的子矩阵,仅包含数字1,所以答案为1。
对于右下角为(1,2)的子矩阵,数字1、2各出现一次,所以答案为2。
对于右下角为(1,3)的子矩阵,数字1、2、3各出现一次,所以答案为3。
对于右下角为(2,1)的子矩阵,数字1、3各出现一次,所以答案为2。
对于右下角为(2,2)的子矩阵,数字2、3各出现一次,但是数字1出现了两次,所以数字1不统计入答案,答案为2。
对于右下角为(2,3)的子矩阵,数字1、2、3均出现了两次,所以答案为0。
【数据说明】
对于10%的数据,有N,M≤10;
对于20%的数据,有N,M≤20;
对于40%的数据,有N,M≤150;
对于50%的数据,A[I, J]≤1000;
对于70%的数据,有N,M≤800;
对于100%的数据,有N,M≤1100,A[I, J] ≤N×M。
Solution :n^4的方法显然是不可行的,仔细仔细思考之下会发现,对于一个矩阵里的某种资源A,只有第一次和第二次出现时是有意义的,于是 我们可以记录下A资源第一次出现的横纵坐标和第二次出现的纵坐标(当然也可以是纵坐标,这个无所谓),然后进行进行一次矩阵的扫 描,对于当前资源K,分类讨论:
Ⅰ:纵坐标比第一次出现的前,这样的的话,累加
ans = (ans + (i-x[k])*(y2[k]-y1[k])) % MO;
Ⅱ:
纵坐标在第一二次之间
,
ans = (ans + (i-x[k])*(y2[k]-j)) % MO;
Ⅲ: 纵坐标在第二次之后?忽略,没有意义。
在统计答案之后,更新x和y1/y2。
这样统计的话,最后会剩下第一次和第二之间的答案没有累加,最后补上。
#include<cstdio>
#define MO 19900907
#define maxn 1111
using namespace std;
int k,ans,n,m,x[maxn*maxn],y1[maxn*maxn],y2[maxn*maxn];
int main(){
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++){
scanf("%d",&k);
if (x[k] == 0){
x[k] = i;
y1[k] = j;
y2[k] = m+1;
continue;
}
if (j < y1[k]){
ans = (ans + (i-x[k])*(y2[k]-y1[k])) % MO;
y2[k] = y1[k];
y1[k] = j;
x[k] = i;
} else {
if (j < y2[k]){
ans = (ans + (i-x[k])*(y2[k]-j)) % MO;
y2[k] = j;
}
}
}
for (int i = 1;i <= n*m;i ++)
if (x[i]){
ans = (ans + (n+1-x[i])*(y2[i]-y1[i])) % MO;
}
printf("%d",ans);
}