zoukankan      html  css  js  c++  java
  • 2018 Multi-University Training Contest 4 Problem E. Matrix from Arrays 【打表+二维前缀和】

    任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6336

    Problem E. Matrix from Arrays

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 1711    Accepted Submission(s): 794


    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 (1T100) denoting the number of test cases.
    Each test case starts with an integer L (1L10) denoting the length of A.
    The second line contains L integers A0,A1,...,AL1 (1Ai100).
    The third line contains an integer Q (1Q100) denoting the number of queries.
    Each of next Q lines consists of four integers x0,y0,x1,y1 (0x0x1108,0y0y1108) 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
     
    Source

    题意概括:

    给一个长度为 L 的序列,要求按照代码的要求构建一个矩阵。

    Q次查询,每次查询输入矩阵的左上角和右下角坐标,输出矩阵的值的总和。

    解题思路:

    并没有什么过人的天分,老老实实把构建的矩阵输出来找规律。

    发现大矩阵是长宽 为 2*L 的小矩阵构造而成的。

    问题就转换为了类似于求矩阵面积的问题,也就可以通过二维前缀和 sum(x, y) 来求解答案。

    例如要求解 (x1, y1, x2, y2) 的值就等于 sum(x2, y2) - sum(x1-1, y2) - sum(x2, y1-1) + sum(x1-1, y1-1);

    如何计算 sum(x, y)呢?首先统计有多少个 2L * 2L 的子矩阵,然后再单独加上这些除掉这些子矩阵的其余部分。

    AC code:

     1 #include<set>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstring>
     6 #include<vector>
     7 #include<queue>
     8 #include<cmath>
     9 #define INF 0x3f3f3f3f
    10 #define LL long long
    11 using namespace std;
    12 const int MAXN = 1e3+10;
    13 LL sum;
    14 int mmp[MAXN][MAXN];
    15 int N, M, L, Q;
    16 LL sum1[MAXN], sum2[MAXN];
    17 int A[MAXN];
    18 
    19 void init()
    20 {
    21     memset(mmp, 0, sizeof(mmp));
    22     memset(sum1, 0, sizeof(sum1));
    23     memset(sum2, 0, sizeof(sum2));
    24     int cnt = 0;
    25     for(int i = 0; i < 4*L; i++){
    26         for(int j = 0; j <= i; j++){
    27             mmp[j][i-j] = A[cnt];
    28             cnt = (cnt+1)%L;
    29         }
    30     }
    31     sum = 0;
    32     for(int i = 0; i < 2*L; i++){
    33         for(int j = 0; j < 2*L; j++){
    34             sum+=mmp[i][j];
    35             sum1[i] += mmp[i][j];
    36             sum2[j] += mmp[i][j];
    37         }
    38     }
    39 }
    40 
    41 LL query(int x, int y)
    42 {
    43     int cnt_x = (x+1)/(2*L);
    44     int cnt_y = (y+1)/(2*L);
    45     LL res = sum*cnt_x*cnt_y;
    46     int lenx = (x+1)%(2*L);
    47     int leny = (y+1)%(2*L);
    48 
    49     for(int i = 0; i < lenx; i++) res+= cnt_y*sum1[i];
    50     for(int j = 0; j < leny; j++) res+= cnt_x*sum2[j];
    51     
    52 
    53     for(int i = 0; i < lenx; i++)
    54         for(int j = 0; j < leny; j++){
    55             res+=mmp[i][j];
    56         }
    57 
    58     return res;
    59 }
    60 
    61 int main()
    62 {
    63     int T_case;
    64     int x1, x2, y1, y2;
    65     scanf("%d", &T_case);
    66     while(T_case--){
    67         scanf("%d", &L);
    68         for(int i = 0; i < L; i++){
    69             scanf("%d", &A[i]);
    70         }
    71         init();
    72         
    73         scanf("%d", &Q);
    74         while(Q--){
    75             scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
    76             LL ans = query(x2, y2)-query(x1-1, y2) - query(x2, y1-1) + query(x1-1, y1-1);
    77             printf("%lld
    ", ans);
    78         }
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    GB/T 38635.1-2020 信息安全技术 SM9标识密码算法 第1部分:总则
    信息安全行业国家标准汇总,信息安全行业从业人员必看
    贪吃蛇游戏(printf输出C语言版本)
    C 实战练习题目57
    C 实战练习题目56
    C 实战练习题目55
    C 实战练习题目54
    C 实战练习题目53
    C 实战练习题目52
    C 实战练习题目51
  • 原文地址:https://www.cnblogs.com/ymzjj/p/10334522.html
Copyright © 2011-2022 走看看