字首和與差分 PAT題目

2021-09-24 20:55:37 字數 3359 閱讀 4680

1.字首和:

字首和是一種預處理,即給出n個數和m組訪問,如果直接每次都在這些數列上操作,會造成超時,字首和直接對這些訪問進行預處理,最後直接得出取出結果進行計算。即o(n+m)。

相關題目:1046 shortest distance

ac**:

#include

#include

#include

#include

#include

#include

#define n 100005

using namespace std;

int s[n]=;

intmain()

,x,y;

cin>>n;

for(

int i=

1;i<=n;i++

) cin>>a[i]

;for

(int i=

1;i<=n;i++

) s[i]

=s[i-1]

+a[i]

; cin>>m;

while

(m--

)return0;

}

2.差分:首先,給出乙個問題:

給出n個數,再給出q個詢問,每個詢問給出le,ri,x,要求你在le到ri上每乙個值都加上x,而只給你o(n)的時間範圍,怎麼辦?

思考一下:

如果暴力,卡一下le和ri,隨隨便便讓你o(n^2)t成狗。

用線段樹或樹狀陣列搞一搞,抱歉,這個複雜度是o(qlogn)的,還是會t(雖然他們解決別的題目很nb)

差分,沒錯,就是標題,很高興o(n)+常數…

方法還是用上面這個題目,假如要在le和ri上全都加乙個x,很顯然,這個o(n)是不可避免的,既然這樣,那我們考慮把o(n*q)變成o(n+q).也就是說,在詢問中我們不去for來加x,而是做乙個標記,最後一起加上。嗯,這裡暫時記住就好…

現在需要自己動筆模擬一下了!

實現先另外開乙個專門差分的陣列(大小=題中的序列長度)

假如在3~8的區間上加上5,那我們在差分陣列中的3位置上加上乙個5(原因暫時不懂沒關係,用筆先跟著模擬),再在8+1的位置上減乙個5,如此操作完q次。

假如我們只有這一次操作,開始統計答案,運用前置和的思想,cfi=cf[i-1]+cf[i].那麼你會發現(如果你模擬了的話),在3~8的區間上,你已經使差分陣列全部加上了5(推廣到所有q一起統計答案依舊正確)

再用o(n)的for把他們加到原序列之中去,輸出!

看一下複雜度,果然:o(常數*n).

自擬題目設計**:

下面還有一道板子題哦!!!

#include

#include

#include

#include

#include

#include

#define n 100005

using namespace std;

int cf[n]=;

intmain()

;int x,y,z;

cin>>n;

for(

int i=

1;i<=n;i++

) cin>>a[i]

; cin>>m;

while

(m--

)for

(int i=

1;i<=n;i++

) cout<

return0;

}

測試結果如下:

案例中給出5個數的數列,進行了3次操作,每次操作乙個範圍。

下面給出一道例題:

牛客北京資訊科技大學第十一屆程式設計競賽(重現賽):andy種樹

這就是一道標準的差分問題,也可以說是模板了。

題目描述:題目描述

andy在他的莊園裡種了n棵樹,排列成一排,標號為1到n。最開始的時候n棵樹的高度都是0,也就是種子剛剛被埋下,樹還沒有長出來。

andy會一種魔法,他每使用一次魔法,就可以讓樹標號落在連續區間[l, r]裡的樹的高度增加1。他可以使用q次這種魔法,然後他很好奇,在使用了q次魔法之後,他的所有樹的高度分別是多少呢?

輸入描述:

第一行輸入兩個整數n,q。(1<= n, q <= 1e5)

接下來q行,每行輸入兩個整數l, r(l <= r),表示andy讓標號落在區間[l, r]裡的數高度都加1

輸出描述:

輸出有一行n個整數,每個整數後面有空格。輸出末尾沒有換行

第i個數表示第i棵樹的高度

示例1輸入

複製10 3

1 32 4

3 3輸出

複製1 2 3 1 0 0 0 0 0 0

說明andy種了10棵樹

第一次使用魔法使得1、2、3棵樹的高度增加1,

所有樹的高度為

1 1 1 0 0 0 0 0 0 0

第二次使用魔法使得2、3、4棵樹的高度增加1,

所有樹的高度為

1 2 2 1 0 0 0 0 0 0

第三次使用魔法使得第3棵樹的高度增加1

所有樹的高度為

1 2 3 1 0 0 0 0 0 0

**展示:

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define n 10001

#define maxn 100005

const

int inf=

0x3f3f3f3f

;const

int p=

109;

typedef

long

long ll;

intmain()

,l,r;

cin>>n>>q;

while

(q--

)for

(int i=

1;i<=n;i++

) f[i]

=f[i]

+f[i-1]

;for

(int i=

1;i<=n;i++

)printf

("%d "

,f[i]);

return0;

}

字首和與差分

數列的字首和 sum i 表示a 1 a i 的和 用處1 求i j的和sum j sum i 1 用處2 區間修改。設定乙個change陣列。當區間 i,j 上要加k時,我們令change i k,令change j 1 k。如果我們對change陣列求字首和的話,字首和sum change i ...

字首和與差分

從陣列第乙個開始累加 s i s i 1 a i 求區間 l,r 的和,o 1 複雜度sum s r s l 1 遞推s i j s i j s i 1 j s i j 1 s i 1 j 1 例題 雷射炸彈一種新型的雷射炸彈,可以摧毀乙個邊長為r的正方形內的所有的目標。現在地圖上有n n 1000...

字首和與差分

例題入口 include const int n 320 int a n n a i 1 a i 0 1.對a 求出平方數 將其值置為1 不是平方數就是0 2.對a求乙個字首和 3.對 a,b 求乙個部分和 int sum n n void init for int i 1 i 100000 i i...