洛谷 P2363 马农

题目描述

分别枚举两个矩阵?那样n^6太要命了。

可以枚举两个矩形的交点
将交点看成原点,可以将整个区域分成四个象限,1与3对应,2与4对应
再枚举相对应的象限计算可以获得的利益,用hash判重

可枚举不同的象限时还要把hash清零,n^2次的memset就超时了。。。

那怎么继续优化呢?

可以用一个栈记录hash里增加的值,只把这些值清零就好了。

#include<complex>
#include<cstdio>
using namespace std;
const int N=51,M=1e6+7;
int n,ans,top;
int st[N*N],sum[N][N],Hash[M<<2];
int main()
{
    scanf("%d",&n);
    int a;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&a);
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a;
        }
    int tmp;
    for(int i=1;i<=n-1;i++)
        for(int j=1;j<=n-1;j++)
        {
            for(int k=1;k<=i;k++)
                for(int l=1;l<=j;l++)
                {
                    tmp=sum[i][j]-sum[k-1][j]-sum[i][l-1]+sum[k-1][l-1]+M;//可能会有负数,所以都加M变为正数 
                    st[++top]=tmp;
                    Hash[tmp]++;
                }
            for(int k=i+1;k<=n;k++)
                for(int l=j+1;l<=n;l++)
                {
                    tmp=sum[i][j]-sum[k][j]-sum[i][l]+sum[k][l]+M;
                    ans+=Hash[tmp];
                }
            while(top)Hash[st[top--]]=0;
            for(int k=i+1;k<=n;k++)
                for(int l=1;l<=j;l++)
                {
                    tmp=sum[i][l-1]-sum[k][l-1]-sum[i][j]+sum[k][j]+M;
                    st[++top]=tmp;
                    Hash[tmp]++;
                }
            for(int k=1;k<=i;k++)
                for(int l=j+1;l<=n;l++)
                {
                    tmp=sum[i][l]-sum[k-1][l]-sum[i][j]+sum[k-1][j]+M;
                    ans+=Hash[tmp];
                }
            while(top)Hash[st[top--]]=0;
        }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/LeTri/p/8675069.html