溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++前綴和與差分如何使用

發(fā)布時間:2023-03-09 09:32:30 來源:億速云 閱讀:124 作者:iii 欄目:開發(fā)技術

本篇內容主要講解“C++前綴和與差分如何使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++前綴和與差分如何使用”吧!

1.一維前綴和

有一個長度為n的數(shù)組an:a1,a2…an;

對于前綴和:Si= a1+a2+…+ai

如何求Si,S[i] = s[i-1]+a[i]

前綴和可以快速求出原數(shù)組里面一段數(shù)的和。比如求一段區(qū)間[l,r],如果按照原來的做法,需要循環(huán)一遍,O(n),有前綴和的算法:

這個區(qū)間的數(shù)就是(Sr) - (sl-1)。同時,為了方便計算令s[0] = 0.比如計算[1,l],既s[l]-s[0] = s[l].

C++前綴和與差分如何使用

其實前綴和就是一個區(qū)間相減的操作,統(tǒng)一處理。前綴和其實是非常簡單的

練習題:

輸入一個長度為 nn 的整數(shù)序列。

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

對于每個詢問,輸出原序列中從第 ll 個數(shù)到第 rr 個數(shù)的和。

輸入格式

第一行包含兩個整數(shù) nn 和 mm。

第二行包含 nn 個整數(shù),表示整數(shù)數(shù)列。

接下來 mm 行,每行包含兩個整數(shù) ll 和 rr,表示一個詢問的區(qū)間范圍。

輸出格式

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

數(shù)據(jù)范圍

1≤l≤r≤n1≤l≤r≤n,

1≤n,m≤1000001≤n,m≤100000,

−1000≤數(shù)列中元素的值≤1000

C++前綴和與差分如何使用

#include <iostream>
using namespace std;
const int N = 100010;
int n,m;
int a[N],S[N];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
    for(int i = 1;i<=n;i++) S[i] = S[i-1]+a[i];
    while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",S[r]-S[l-1]);
    }
    return 0;
}

2.二維前綴和

二維前綴和是在一個二維矩陣里求子矩陣的和

C++前綴和與差分如何使用

C++前綴和與差分如何使用

練習題:

輸入一個 nn 行 mm 列的整數(shù)矩陣,再輸入 qq 個詢問,每個詢問包含四個整數(shù) x1,y1,x2,y2x1,y1,x2,y2,表示一個子矩陣的左上角坐標和右下角坐標。

對于每個詢問輸出子矩陣中所有數(shù)的和。

輸入格式

第一行包含三個整數(shù) n,m,qn,m,q。

接下來 nn 行,每行包含 mm 個整數(shù),表示整數(shù)矩陣。

接下來 qq 行,每行包含四個整數(shù) x1,y1,x2,y2x1,y1,x2,y2,表示一組詢問。

輸出格式

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

數(shù)據(jù)范圍

1&le;n,m&le;10001&le;n,m&le;1000,

1&le;q&le;2000001&le;q&le;200000,

1&le;x1&le;x2&le;n1&le;x1&le;x2&le;n,

1&le;y1&le;y2&le;m1&le;y1&le;y2&le;m,

&minus;1000&le;矩陣內元素的值&le;1000\

C++前綴和與差分如何使用

#include <iostream>
using namespace std;
const int N = 1010;
int n,m,q;
long a[N][N],s[N][N];
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for(int i = 1;i<=n;i++)
    {
        for(int 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--)
    {
        int x1,y1,x2,y2;
        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;
}

3.一維差分

給定a[1],a[2],&hellip;,a[n]構造差分數(shù)組b[N],使得a[i] = b[1]+b[2]+&hellip;+b[i]

b1 = a1,b2 = a2-a1,b3 = a3-a2,直到bn = an-an-1

b是a的差分,a是b的前綴和。有b數(shù)組就可以通過O(n)的時間復雜度得到a數(shù)組。

推導過程:

現(xiàn)在在a數(shù)組[L,R]中全部加上C,那就是al+C,al+1+C,&hellip;,ar+C,通過暴力的方式O(n)可以求解,那差分可以變成O(1)

在[L,R]中,如果我們在b數(shù)組bl+C,那么al也會加上C,al+1也會加上C&hellip;an+1也會加上C,因為每一次都會加上一個bl。但是我們只要al到ar加上C,那么ar后面不要加上C,那么我們直接讓br-c即可完成數(shù)組a在[L,R]范圍里全部加上C。

核心操作是將a[L~R]全部加上C等價于b[L] +=C,b[R+1]-=C

C++前綴和與差分如何使用

把O(n)提高到O(1)

假定a數(shù)組全是初始化為0,那b數(shù)組也是全為0,但是題目a數(shù)組并不是0,我們可以看成進行n次插入操作,第一次是在原數(shù)組a[1,1]加上a1,第二次是在原數(shù)組a[2,2]加上a2&hellip;以此類推即可,所以并不需要去想如何構造差分

題目:

輸入一個長度為 nn 的整數(shù)序列。

接下來輸入 mm 個操作,每個操作包含三個整數(shù) l,r,cl,r,c,表示將序列中 [l,r][l,r] 之間的每個數(shù)加上 cc。

請你輸出進行完所有操作后的序列。

輸入格式

第一行包含兩個整數(shù) nn 和 mm。

第二行包含 nn 個整數(shù),表示整數(shù)序列。

接下來 mm 行,每行包含三個整數(shù) l,r,cl,r,c,表示一個操作。

輸出格式

共一行,包含 nn 個整數(shù),表示最終序列。

數(shù)據(jù)范圍

1&le;n,m&le;1000001&le;n,m&le;100000,

1&le;l&le;r&le;n1&le;l&le;r&le;n,

&minus;1000&le;c&le;1000&minus;1000&le;c&le;1000,

&minus;1000&le;整數(shù)序列中元素的值&le;1000

C++前綴和與差分如何使用

#include <iostream>
using namespace std;
const int N = 100010;
int n,m;
int a[N],b[N];
void insert(int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}
int main()
{
    cin>>n>>m;
    for(int i = 1;i<=n;i++)
    {
        cin>>a[i];
        insert(i,i,a[i]);
    }
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);
    }
    for(int i = 1;i<=n;i++) a[i] = a[i-1]+b[i];
    for(int i = 1;i<=n;i++) printf("%d ",a[i]);
    return 0;
}

4.二維差分

二維差分也是一樣的道理

C++前綴和與差分如何使用

練習題:

輸入一個 nn 行 mm 列的整數(shù)矩陣,再輸入 qq 個操作,每個操作包含五個整數(shù) x1,y1,x2,y2,cx1,y1,x2,y2,c,其中 (x1,y1)(x1,y1) 和 (x2,y2)(x2,y2) 表示一個子矩陣的左上角坐標和右下角坐標。

每個操作都要將選中的子矩陣中的每個元素的值加上 cc。

請你將進行完所有操作后的矩陣輸出。

輸入格式

第一行包含整數(shù) n,m,qn,m,q。

接下來 nn 行,每行包含 mm 個整數(shù),表示整數(shù)矩陣。

接下來 qq 行,每行包含 55 個整數(shù) x1,y1,x2,y2,cx1,y1,x2,y2,c,表示一個操作。

輸出格式

共 nn 行,每行 mm 個整數(shù),表示所有操作進行完畢后的最終矩陣。

數(shù)據(jù)范圍

1&le;n,m&le;10001&le;n,m&le;1000,

1&le;q&le;1000001&le;q&le;100000,

1&le;x1&le;x2&le;n1&le;x1&le;x2&le;n,

1&le;y1&le;y2&le;m1&le;y1&le;y2&le;m,

&minus;1000&le;c&le;1000&minus;1000&le;c&le;1000,

&minus;1000&le;矩陣內元素的值&le;1000

C++前綴和與差分如何使用

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

到此,相信大家對“C++前綴和與差分如何使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

c++
AI