• HDU


    原题链接

    题意:

    给定一种矩阵生成方式,现在给一个数组 $A$ ,然后询问某个子矩阵的和,$x,y<1e8$;

    思路:

    矩阵是无限大的,所求的子矩阵范围也较大,于是就表找规律,发现当$L$为奇数时,周期为$L$,反之为$2*L$;

    那么我们就可以把周期一致看作$2*L$,然后做一下前缀和,就可以直接求了。此类题目要善于总结!

     1 /*
     2 * @Author: windystreet
     3 * @Date:   2018-08-06 10:27:38
     4 * @Last Modified by:   windystreet
     5 * @Last Modified time: 2018-08-06 20:48:57
     6 */
     7 #include<bits/stdc++.h>
     8 
     9 using namespace std;
    10 
    11 #define X first
    12 #define Y second
    13 #define eps  1e-5
    14 #define gcd __gcd
    15 #define pb push_back
    16 #define PI acos(-1.0)
    17 #define lowbit(x) (x)&(-x)
    18 #define bug printf("!!!!!
    ");
    19 #define mem(x,y) memset(x,y,sizeof(x))
    20 
    21 typedef long long LL;
    22 typedef long double LD;
    23 typedef pair<int,int> pii;
    24 typedef unsigned long long uLL;
    25 
    26 const int maxn = 1e5+2;
    27 const int INF  = 1<<30;
    28 const int mod  = 1e9+7;
    29 
    30 int s[110][110];
    31 int a[100];
    32 int sum[110][110];
    33 int L;
    34 
    35 LL cal(int s,int t){                                           // 计算(0,0,)到(s,t)的前缀和
    36     int x = s%L,cntx = s/L;
    37     int y = t%L,cnty = t/L;
    38     return 1ll*sum[x][L-1]*cnty+1ll*sum[L-1][y]*cntx+1ll*sum[L-1][L-1]*cntx*cnty+1ll*sum[x][y];
    39 }
    40 
    41 void solve(){
    42     int Q,x1,y1,x2,y2;
    43     scanf("%d",&L);
    44     for(int i=0;i<L;i++){
    45         scanf("%d",&a[i]);
    46     }
    47     int cur = 0;
    48     for(int i=0;i<10*L;++i){                                // 矩阵生成器
    49         for(int j=0;j<=i;++j){
    50             s[j][i-j] = a[cur];
    51             cur = (cur + 1) % L;
    52         }
    53     }
    54     L = 2*L;
    55     sum[0][0] = s[0][0];                                    // 计算(2*L)*(2*L)矩阵的前缀和
    56     for(int i=1;i<L;i++)sum[0][i] = sum[0][i-1] + s[0][i];
    57     for(int i=1;i<L;i++)sum[i][0] = sum[i-1][0] + s[i][0];
    58     for(int i=1;i<L;i++){
    59         for(int j=1;j<L;j++){
    60             sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + s[i][j];
    61         }
    62     }
    63     scanf("%d",&Q);
    64     while(Q--){
    65         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);                    // 容斥一下
    66            printf("%lld
    ",cal(x2,y2)-cal(x2,y1-1)-cal(x1-1,y2)+cal(x1-1,y1-1));
    67     }
    68     return;
    69 }
    70 
    71 int main()
    72 {
    73 //    freopen("in.txt","r",stdin);
    74 //    freopen("out.txt","w",stdout);
    75 //    ios::sync_with_stdio(false);
    76     int t = 1;
    77     scanf("%d",&t);
    78     while(t--){
    79     //    printf("Case %d: ",cas++);
    80         solve();
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    第三天
    第二天
    第一天
    构建之法阅读笔记06
    返回一个一维整数数组中最大子数组的和2
    团队介绍
    软件工程结对作业02
    返回一个整数数组中最大子数组的和
    构建之法阅读笔记05
    暑假周总结二7.22
  • 原文地址:https://www.cnblogs.com/windystreet/p/9432919.html
Copyright © 2020-2023  润新知