洛谷 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\n",ans); return 0; }