Problem E. Matrix from Arrays
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1386 Accepted Submission(s): 630
Problem Description
Kazari has an array A length of L, she plans to generate an infinite matrix M using A.
The procedure is given below in C/C++:
int cursor = 0;
for (int i = 0; ; ++i) { for (int j = 0; j <= i; ++j) { M[j][i - j] = A[cursor]; cursor = (cursor + 1) % L; } } Her friends don't believe that she has the ability to generate such a huge matrix, so they come up with a lot of queries about M, each of which focus the sum over some sub matrix. Kazari hates to spend time on these boring queries. She asks you, an excellent coder, to help her solve these queries.
Input
The first line of the input contains an integer T (1≤T≤100) denoting the number of test cases.
Each test case starts with an integer L (1≤L≤10) denoting the length of A.
The second line contains L integers A0,A1,...,AL−1 (1≤Ai≤100).
The third line contains an integer Q (1≤Q≤100) denoting the number of queries.
Each of next Q lines consists of four integers x0,y0,x1,y1 (0≤x0≤x1≤108,0≤y0≤y1≤108) querying the sum over the sub matrix whose upper-leftmost cell is (x0,y0) and lower-rightest cell is (x1,y1).
Output
For each test case, print an integer representing the sum over the specific sub matrix for each query.
Sample Input
1
3
1 10 100
5
3 3 3 3
2 3 3 3
2 3 5 8
5 1 10 10
9 99 999 1000
Sample Output
1
101
1068
2238
33076541
题意:由一个原始数组,通过公式构造成一个二维数组,求二维数组中子矩阵的和。
for (int i = 0; ; ++i) {
for (int j = 0; j <= i; ++j) {
M[j][i - j] = A[cursor];
cursor = (cursor + 1) % L;
}
}
这种方式构造出来的二维数组是有规律的,会以L*L的矩阵为单位,反复出现,例如例题中的:A:1 10 100。
1
3
1 10 100
1 10 1 1 10 1 1 10 1 1
100 10 10 100 10 10 100 10 10 100
100 100 1 100 100 1 100 100 1 100
1 10 1 1 10 1 1 10 1 1
100 10 10 100 10 10 100 10 10 100
100 100 1 100 100 1 100 100 1 100
1 10 1 1 10 1 1 10 1 1
100 10 10 100 10 10 100 10 10 100
100 100 1 100 100 1 100 100 1 100
1 10 1 1 10 1 1 10 1 1
可以通过sum[][],将每个区间矩阵的和算出来。
#include <bits/stdc++.h>
using namespace std;
#define max(a,b) (a>b?a:b)
#define ll long long
int L;
ll M[500][500],sum[500][500],A[1120];
ll node(ll x,ll y){
ll a = x / L;
ll b = y / L;
x = x % L;
y = y % L;
return a * b *sum[L-1][L-1] + a* sum[L-1][y] + b* sum[x][L-1] +sum[x][y];
}
int main() {
int T,Q;
scanf("%d",&T);
while(T--) {
scanf("%d",&L);
for(int i=0; i<L; i++)
scanf("%lld",&A[i]);
int cursor = 0;
for(int i=0; i<110; i++) {
for(int j=0; j<=i; j++) {
M[j][i-j] = A[cursor];
cursor = (cursor+1) % L;
}
}
if(L % 2 == 0)
L *= 2;
sum[0][0] = M[0][0];
for(int i=0;i<L;i++){
for(int j =0;j<L;j++){
if(i ==0 && j ==0 ){//begin
sum[i][j] = M[i][j];
}
if(i == 0){
sum[i][j] = sum[i][j-1] + M[i][j];
}
else if(j == 0 )
sum[i][j] = sum[i-1][j] + M[i][j];
else
sum[i][j] = sum[i-1][j] +sum[i][j-1] + M[i][j] - sum[i-1][j-1];
}
}
scanf("%d",&Q);
for(int i=0;i<Q;i++){
ll x0,y0,x1,y1;
scanf("%lld %lld %lld %lld",&x0,&y0,&x1,&y1);
printf("%lld\n",node(x1,y1) - node(x0-1,y1)-node(x1,y0-1)+node(x0-1,y0-1));
}
}
}