HDU 5749 BestCoder Round #84 Colmerauer(暴力贡献)

23 篇文章 0 订阅
13 篇文章 0 订阅

Colmerauer

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 220    Accepted Submission(s): 94

Problem Description
Peter has an n×m matrix M . Let S(a,b) be the sum of the weight all a×b submatrices of M . The weight of matrix is the sum of the value of all the saddle points in the matrix. A saddle point of a matrix is an element which is both the only largest element in its column and the only smallest element in its row. Help Peter find out all the value of S(a,b) .

Note: the definition of saddle point in this problem may be different with the definition you knew before.

Input
There are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case:
The first contains two integers n and m (1n,m1000) -- the dimensions of the matrix.
The next n lines each contain m non-negative integers separated by spaces describing rows of matrix M (each element of M is no greater than 106 ).

Output
For each test case, output an integer W=(a=1nb=1mabS(a,b)) mod 232 .
Sample Input
  
  
3 2 2 1 1 1 1 3 3 1 2 3 4 5 6 7 8 9 3 3 1 2 1 2 3 1 4 5 2
Sample Output
  
  
4 600 215
Source
Recommend
wange2014   |   We have carefully selected several similar problems for you:  5751 5750 5746 5745 5744 
 
题解:

Peter有一个n×m的矩阵M.定义S(a,b)为M的所有大小为a×b的子矩阵的权值和.一个矩阵的权值是这个矩阵所有鞍点的值的和.在矩阵中,一个数在所在行中是唯一的最小值,在所在列中是唯一的最大值,则被称为鞍点.帮助Peter找出所有S(a,b)的值. 

输出:

已知一个点的Up,Down,Left,Right,即上下左右的扩展范围,然后计算鞍点对答案的贡献

把所有可能的矩形的长算出来,得到和,宽也是一样,然后按照乘法原理乘起来就好。

详细题解:BestCoder Round #84 (点击)Orz。。。

AC代码:

//#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<algorithm>
#define N 1010
using namespace std;
int n,m;
int a[N][N];
int stk[N],top;
int L[N][N],R[N][N],U[N][N],D[N][N];
int readint()
{
	char c;
	while((c=getchar())&&!(c>='0' && c<='9'));
	int ret= c- 48;
	while((c=getchar())&&( c>='0' && c<='9'))
	ret = ret * 10 + c-48;
	return ret;
}
unsigned int calc(int l,int x,int r)
{
	unsigned int d1=r-x+1;
	unsigned int d2=x-l+1;
	unsigned int ret=d1 * (d1+1) / 2 * d2 + d2* (d2-1)/2 *d1;
	return ret;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=m;j++)
    		{
    			a[i][j]=readint();
			}
		}
		for(int i=1;i<=n;i++)
		{
			top=0;
			for(int j=1;j<=m;j++)
			{
				while(top && a[i][stk[top-1]] > a[i][j])
				--top;
				if(top==0) L[i][j]=1;
				else L[i][j]=stk[top-1]+1;
				stk[top++]=j;
			}
		}
		for(int i=1;i<=n;i++)
		{
			top=0;
			for(int j=m;j>=1;--j)
			{
				while(top && a[i][stk[top-1]] > a[i][j])
				--top;
				if(top==0) R[i][j]=m;
				else R[i][j] = stk[top-1] - 1;
				stk[top++] = j;
			}
		}
		for(int i=1;i<=m;i++)
		{
			top=0;
			for(int j=1;j<=n;j++)
			{
				while(top && a[stk[top-1]][i] < a[j][i])
				--top;
				if(top==0) U[j][i]=1;
				else U[j][i] = stk[top-1]+1;
				stk[top++]=j;
			}
	  }
	  for(int i=1;i<=m;i++)
	  {
			top=0;
			for(int j=n;j>=1;--j)
			{
				while(top && a[stk[top-1]][i] < a[j][i])
				--top;
				if(top==0) D[j][i]=n;
				else D[j][i] = stk[top-1]-1;
				stk[top++]=j;
			}
		}
		unsigned int ans=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				ans += (unsigned int)a[i][j]*calc(L[i][j],j,R[i][j])*calc(U[i][j],i,D[i][j]);
			}
		}
		printf("%u\n",ans);
	}
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值