前綴和算法


(一)前綴和算法

概念:前綴和就是數組的前i項之和

一維前綴和

s[1]=a[1]

s[2]=a[1]+a[2]

s[3]=a[1]+a[2]+a[3]

s[4]=a[1]+a[2]+a[3]+a[4]

s[5]=a[1]+a[2]+a[3]+a[4]+a[5]

①.前綴和

輸入一個長度為n的整數序列。

接下來再輸入m個詢問,每個詢問輸入一對l, r。

對於每個詢問,輸出原序列中從第l個數到第r個數的和。

輸入格式

第一行包含兩個整數n和m。

第二行包含n個整數,表示整數數列。

接下來m行,每行包含兩個整數l和r,表示一個詢問的區間范圍。

輸出格式

共m行,每行輸出一個詢問的結果。

數據范圍

1lrn,
1n,m100000,
10001000

輸入樣例:

5 3 2 1 3 6 4 1 2 1 3 2 4 

輸出樣例:

3 6 10
#include<iostream>
using namespace std;
int main()
{
    int sum,n,i,j,x,m,l,r;
    int s[100009];
    cin>>n>>m;
    sum=0;
    for(i=1;i<=n;i++)
    {
        cin>>x;
        sum+=x;
        s[i]=sum;
    }
    for(i=0;i<m;i++)
    {
        cin>>l>>r;
        cout<<s[r]-s[l-1]<<endl;
    }
    return 0;
}
 

在做題中我們會經常用到他的二維的前綴和數組

最常見的案例:求子矩陣的和

2.子矩陣的和

輸入一個n行m列的整數矩陣,再輸入q個詢問,每個詢問包含四個整數x1, y1, x2, y2,表示一個子矩陣的左上角坐標和右下角坐標。

對於每個詢問輸出子矩陣中所有數的和。

輸入格式

第一行包含三個整數n,m,q。

接下來n行,每行包含m個整數,表示整數矩陣。

接下來q行,每行包含四個整數x1, y1, x2, y2,表示一組詢問。

輸出格式

共q行,每行輸出一個詢問的結果。

數據范圍

1n,m1000,
1q200000,
1x1x2n,
1y1y2m,
10001000

輸入樣例:

3 4 3 1 7 2 4 3 6 2 8 2 1 2 3 1 1 2 2 2 1 3 4 1 3 3 4 

輸出樣例:

17 27 21

對於二維前綴和問題,首先我們先求出他的前綴和數組,如何求呢?
對於(i,j)該點的前綴和數組求解:看圖,求紅色部分的前綴和

 

 
            

 就可以看成是藍色前綴和+粉色前綴和-黃色前綴和+自己本身

s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]

 

 求完前綴和數組后,在分析一下如果要求兩個點之間的子矩陣的和應該怎么辦?

再畫圖分析一下:

 

 求解兩個圓圈之間的子矩陣:黃色面積-藍色面積-紫色面積+粉色面積

ans=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]

代碼:

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,q,x1,x2,y1,y2;
int s[1010][1010],a[1010][1010];
int main()
{
    int i,j;
    scanf("%d%d%d",&n,&m,&q);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
        }
    }
    while(q--)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%d\n",s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]);
    }
    return 0;
}

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM