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...