CF上10^8并不会超时(TL为1S)
题目大意:在给定的n,m的矩阵中问在以l1,r1,l2,r2为边界的矩阵1*2的骨牌有多少种不同的放法。
思路:看了题解才知道这是一种二维前缀和- -。放骨牌的话只有两种放法横着和竖着。那么可以设两个二维数组
分别装横与竖着的前缀数组。然后再枚举两个符合的区间。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<string> #include<queue> #include<map> #define L1 long long #define L2 __int64 #define inf 0x3f3f3f3f using namespace std; const int m1=1001000; const int m2=1010; int head[m1],vex[m1],arr[m1]; bool vis[m2][m2]; char s[510][510]; int dp1[510][510],dp2[510][510]; int main() { int l1,l2,r1,r2,n,m,i,k,j; while(~scanf("%d%d",&n,&m)) { getchar(); for(i=1;i<=n;i++) { scanf("%s",s[i]+1); } memset(dp1,0,sizeof(dp1)); memset(dp2,0,sizeof(dp2)); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(s[i][j]=='.'&&s[i][j-1]=='.') { dp1[i][j]=dp1[i][j-1]+1; } else dp1[i][j]=dp1[i][j-1]; } } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(s[i][j]=='.'&&s[i-1][j]=='.') dp2[i][j]=dp2[i-1][j]+1; else dp2[i][j]=dp2[i-1][j]; } } scanf("%d",&k); while(k--) { scanf("%d%d%d%d",&l1,&r1,&l2,&r2); L1 ans=0; for(i=l1;i<=l2;i++) { ans+=(dp1[i][r2]-dp1[i][r1]); } for(i=r1;i<=r2;i++) { ans+=(dp2[l2][i]-dp2[l1][i]); } printf("%lld\n",ans); } } return 0; }