Hdu 5749 Colmerauer

来源:互联网 发布:魔兽争霸mac无法打开 编辑:程序博客网 时间:2024/06/04 01:20

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

思路:”’现在出每个点成为鞍点的行和列的范围,然后计算鞍点对答案的贡献,注意面积的计算可以转化为长*宽”’

#include<bits/stdc++.h>using namespace std;const int maxn=1010;int l[maxn][maxn],r[maxn][maxn],up[maxn][maxn],down[maxn][maxn];int a[maxn][maxn];unsigned int dp[maxn][maxn];int read(){   char ch=getchar(),last=' ';   while(ch<'0' || ch>'9')last=ch,ch=getchar();   int ans=0;   while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();   if(last=='-')ans=-ans;   return ans;}int main(){    for(int i=1;i<maxn;i++)        for(int j=1;j<maxn;j++)            dp[i][j]=dp[i][j-1]+(1LL*i*(2*j+i-1)/2);    int _=read(),n,m;    while(_--){        n=read(),m=read();        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                a[i][j]=read();        for(int i=1;i<=n;i++){            l[i][1]=1;            for(int j=2;j<=m;j++){                int tmp=j;                while(tmp!=1&&a[i][j]<a[i][tmp-1])                    tmp=l[i][tmp-1];                l[i][j]=tmp;            }        }        for(int i=1;i<=n;i++){            r[i][m]=m;            for(int j=m-1;j>=1;j--){                int tmp=j;                while(tmp!=m&&a[i][j]<a[i][tmp+1])                    tmp=r[i][tmp+1];                r[i][j]=tmp;            }        }        for(int i=1;i<=m;i++){            up[1][i]=1;            for(int j=2;j<=n;j++){                int tmp=j;                while(tmp!=1&&a[j][i]>a[tmp-1][i])                    tmp=up[tmp-1][i];                up[j][i]=tmp;            }        }        for(int i=1;i<=m;i++){            down[n][i]=n;            for(int j=n-1;j>=1;j--){                int tmp=j;                while(tmp!=n&&a[j][i]>a[tmp+1][i])                    tmp=down[tmp+1][i];                down[j][i]=tmp;            }        }//        for(int i=1;i<=n;i++)//            for(int j=1;j<=m;j++)//                printf("%d %d %d %d %d %d\n",i,j,up[i][j],down[i][j],l[i][j],r[i][j]);        unsigned int ans=0;        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)                ans=ans+dp[j-l[i][j]+1][r[i][j]-j+1]*dp[i-up[i][j]+1][down[i][j]-i+1]*a[i][j];        printf("%u\n",ans);    }    return 0;}
0 0
原创粉丝点击