二维前缀和 - 算法学习 - 输入输出优化

2017-08-27 11:11:38

writer:pprp

二维前缀和主要用到了容斥定理,具体实现还是有点复杂的

详见代码:

/*
@theme:二维前缀和
@writer:pprp
@declare:用到容斥定理
@date:2017/8/27
*/

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1010;

int n, m, a[maxn][maxn];

//输入优化
inline int read()
{
    int X=0,w=1;
    char ch=0;
    while(ch<‘0‘ || ch>‘9‘)
    {
        if(ch==‘-‘) w=-1;
        ch=getchar();
    }
    while(ch>=‘0‘ && ch<=‘9‘) X=(X<<3)+(X<<1)+ch-‘0‘,ch=getchar();
    return X*w;
}

inline void write(int x)
{
    if(x<0) putchar(‘-‘),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+‘0‘);
}

int main()
{
    freopen("in.txt","r",stdin);
    n = read();
    m = read();
    a[0][0] = read();

    //前n向子矩阵和的求法
    for(int i = 1; i < n ; i++)
    {
        a[0][i] = read();
        a[0][i] += a[0][i-1];
    }
    //这段的实现比较复杂
    for(int i = 1; i < n ; i++)
    {
        a[i][0] = read();
        a[i][0] += a[i-1][0];
        for(int j = 1; j < n ; j++)
        {
            a[i][j] = read();
            //容斥原理
            a[i][j] = a[i][j] + a[i-1][j] + a[i][j-1] - a[i-1][j-1];
        }
    }

    for(int i = 0 ; i < m ; i++)
    {
        int x, y, x1, y1;
        x = read();
        y = read();
        x1 = read();
        y1 = read();
        //write(a[x1-1][y1-1]-a[x-2][y1-1]-a[x1-1][y-2]+a[x-2][y-2]);
        //如果这样写就有问题了,因为如果考虑边界情况,在x = 1||y = 1的时候,会减去a[x1-1][-1],减去不存在的数
        //所以需要判断四种情况
        if(x==1 && y==1)
        {
            write(a[x1-1][y1-1]);
        }
        else if(x==1)
        {
            write(a[x1-1][y1-1]-a[x1-1][y-2]);
        }
        else if(y==1)
        {
            write(a[x1-1][y1-1]-a[x-2][y1-1]);
        }
        else
        {
            write(a[x1-1][y1-1]-a[x-2][y1-1]-a[x1-1][y-2]+a[x-2][y-2]);//输出结果,单次O(1),总共O(m)
        }
        putchar(‘\n‘);
    }
    return 0;
}
时间: 2024-10-09 01:53:25

二维前缀和 - 算法学习 - 输入输出优化的相关文章

二维前缀和

一维前缀和 : 这个优化 , 可以在 O (1) 的时间内计算出一个序列的和 , 二维前缀和 : 对于一个矩阵 , 也可以在 O (1) 的时间内计算出矩阵 (x1~x2)( y1 ~ y2 ) 的和 . sum[ i ] [ j ] 表示矩阵 1 ~ i , 1 ~ j 的和 , 那么由容斥原理知 sum[ 0 ] [ j ] 和 sum [ i ] [ 0 ] 均为 0 . 则  s[ x1 ~ x2 ] [ y1 ~ y2 ] = sum[ x2 , y2 ] + sum [ x1 - 1

Memento Mori (二维前缀和 + 枚举剪枝)

枚举指的是枚举矩阵的上下界,然后根据p0, p1, p2的关系去找出另外的中间2个点.然后需要记忆化一些地方防止重复减少时间复杂度.这应该是最关键的一步优化时间,指的就是代码中to数组.然后就是子矩阵的一个计算了,需要用二维前缀和预处理数据,然后判断的时候直接O(1)查询就好了. #include<bits/stdc++.h> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 2e3 + 7; struct no

【luogu2038】【noip2014】无线网络发射器选址 [模拟][二维前缀和]

P2038 无线网络发射器选址 这个题有很多种做法 然后就可以练很多小的算法 技巧啥的嘿嘿 首先是模拟 要开一个为128+40为边长的数组 然后枚举在20~148内以(i,j)为中心的正方形 然后再挨个挨个计算sum 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define rg register 4 #define ll long long 5 const int N=200; 6 int n,d,mp[N][N]; 7 templ

[计算机图形学 with OpenGL] Chapter8 习题8.12 NLN二维线段裁剪算法实现

Nicholl-Lee-Nicholl二维线段裁剪算法相对于Cohen-Sutherland和Liang-Barsky算法来说,在求交点之前进行了线段端点相对于几个区域的判断,可以确切的知道要求交点的边的信息. 此方法只在二维空间裁剪时使用,C-S和L-B裁剪方法则可应用到三维空间. 算法步骤: 1 先使用C-S裁剪算法的区域码判断方法,去除一部分在裁剪区域外面的线段.显示在完全在裁剪区域内的线段.其他不能判断的情况,采用NLN算法进行裁剪. 2 p1和p2若有一点在区域内,必要时交换端点以确保

openjudge1768 最大子矩阵[二维前缀和or递推|DP]

总时间限制:  1000ms 内存限制:  65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 09 2 -6 2-4 1 -4 1-1 8 0 -2 的最大子矩阵是 9 2-4 1-1 8 这个子矩阵的大小是15. 输入 输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给

Good Bye 2015 C. New Year and Domino 二维前缀

C. New Year and Domino They say "years are like dominoes, tumbling one after the other". But would a year fit into a grid? I don't think so. Limak is a little polar bear who loves to play. He has recently got a rectangular grid with h rows and w

编程题:指向二维数组元素的指针变量。功能:已知二维数组a[2][3],输入输出全部元素。

#include<stdio.h> void main() { int a[2][3],i,j; int *p; /*用坐标法输入二维数组元素*/ for(i=0;i<2;i++) for(j=0;j<3;j++) scanf("%d",&a[i][j]); /*用指针法输出二维数组元素*/ p=a[0];         /*等价于p&a[0][0];*/ for(;p<a[0]+6;p++)   printf("%4d&quo

计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和

题目链接:https://nanti.jisuanke.com/t/16445 题意: 给你一个n*n大小的01矩阵,和一个k*k大小的锤子,锤子只能斜着砸,问只砸一次最多能砸到多少个1. 题解: 将原矩阵顺时针旋转45°,二维前缀和预处理,然后枚举每一个可能砸到的正方形之和并取最大. 注:枚举的正方形的四个顶点必须是从原矩阵璇转过来的点,代码中用vis数组判断. #include <iostream> #include <stdio.h> #include <string.

弱校联盟10.7 I. Special Squares(二维前缀和)

题目链接: I. Special Squares There are some points and lines parellel to x-axis or y-axis on the plane. If arbitrary chosen two lines parallel to x-axis and two lines parallel to y-axis, one rectangle, or sometimes a square, will be formed. If a square i