6336.Problem E. Matrix from Arrays
不想解释了,直接官方题解:
队友写了博客,我是水的他的代码
------>HDU 6336 子矩阵求和
至于为什么是4倍的,因为这个矩阵是左上半边有数,所以开4倍才能保证求的矩阵区域里面有数,就是图上的红色阴影部分,蓝色为待求解矩阵。
其他的就是容斥原理用一下,其他的就没什么了。
代码:
1 //1005-6336-矩阵求和-二维前缀和+容斥-预处理O(1)查询输出 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<bitset> 7 #include<cassert> 8 #include<cctype> 9 #include<cmath> 10 #include<cstdlib> 11 #include<ctime> 12 #include<deque> 13 #include<iomanip> 14 #include<list> 15 #include<map> 16 #include<queue> 17 #include<set> 18 #include<stack> 19 #include<vector> 20 using namespace std; 21 typedef long long ll; 22 23 const double PI=acos(-1.0); 24 const double eps=1e-6; 25 const ll mod=1e9+7; 26 const int inf=0x3f3f3f3f; 27 const int maxn=100+10; 28 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 29 30 ll n,a[maxn],sum[maxn][maxn]; 31 32 void init() 33 { 34 int cnt=0; 35 for(int i=0;i<4*n;++i){ 36 for(int j=0;j<=i;++j){ 37 sum[j][i-j]=a[cnt]; 38 cnt=(cnt+1)%n; 39 } 40 } 41 for(int i=0;i<2*n;i++){ 42 for(int j=0;j<2*n;j++){ 43 if(i> 0&&j> 0) sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; 44 if(i==0&&j> 0) sum[i][j]+=sum[i][j-1]; 45 if(i> 0&&j==0) sum[i][j]+=sum[i-1][j]; 46 } 47 } 48 } 49 50 ll GetAns(int x,int y) 51 { 52 ll ans=0; 53 ans+=(x/n)*(y/n)*sum[n-1][n-1]; 54 ans+=(y/n)*sum[x%n][n-1]; 55 ans+=(x/n)*sum[n-1][y%n]; 56 ans+=sum[x%n][y%n]; 57 return ans; 58 } 59 60 int main() 61 { 62 int t;scanf("%d",&t); 63 while(t--){ 64 scanf("%lld",&n); 65 for(int i=0;i<n;i++) 66 scanf("%lld",&a[i]); 67 init(); 68 n=n*2; 69 int m;scanf("%d",&m); 70 for(int i=0;i<m;i++){ 71 int x1,y1,x2,y2; 72 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 73 ll ans=GetAns(x2,y2)-GetAns(x1-1,y2)-GetAns(x2,y1-1)+GetAns(x1-1,y1-1);//容斥 74 printf("%lld ",ans); 75 } 76 } 77 }
溜了。