如果我給你一串長度為n的數列a1,a2,a3…an,再給出m個詢問,每次詢問給出l,r兩個數,要求給出區間[l,r]裡的數的和,你會怎麼做,若是沒有了解過字首和的人看到這道題的想法可能是對於m次詢問,我每次都遍歷一遍它給的區間,計算出答案,這樣子的方法固然沒錯,但是用了兩個迴圈,其時間複雜度達到了o(n*n),如果資料量稍微大一點就有可能超時,而我們如果使用字首和的方法來做的話就能夠將時間複雜度降到o(n+m),大大節省了運算時間。
int tr[1005] = ;
for(int i = 1; i <= n; i++)
tr[i] += tr[i - 1];
然後你需要哪個區間的數的和,就可以用tr[r] - tr[l - 1]
給你一串長度為n的數列a1,a2,a3…an,要求對a[l]~a[r]進行m次操作:
操作一:將a[l]~a[r]內的元素都加上p
操作二:將a[l]~a[r]內的元素都減去p
最後再給出乙個詢問求a[l]-a[r]內的元素之和?
你會怎麼做呢?你可能會想,我對於m次操作每次都遍歷一遍a[l]~a[r],給區間裡的數都加上p或減去p,最後再求一次字首和就行了。沒錯,這樣子確實也能得出正確答案,但時間複雜度卻高達o(m*n+q),對於1<=n,m<=1e5這個資料範圍來說直接就tle了,所以說這個方法不可行。這個時候差分就派上了用場,我們可以用另乙個差分陣列br來儲存每一步操作,比如對[a,b]的元素同時加c,那麼我們可以讓br[a]+=c,br[b + 1]-=c,這樣的話求一遍字首和就能讓區間內的所有數都加c
#includeusing namespace std;
int main()
; int br[10005] = ;//差分陣列
int n, m, a, b, c;
int add = 0;
cin>>n>>m;//n是陣列個數,m是進行的操作次數
for(int i = 1; i <= n; i++)
for(int i = 1; i <= m; i++)
for(int i = 1; i <= n; i++)
cin>>a>>b;//輸入所需輸出的區間
cout《牛牛澆樹
題目描述
牛牛現在在花園養了n棵樹,按順序從第1棵到第n棵排列著。牛牛每天會按照心情給其中某乙個區間的樹澆水。例如如果某一天澆水的區間為[2,4],就是牛牛在這一天會給第2棵,第3棵和第4棵樹澆水。樹被澆水後就會成長,為了簡化問題,我們假設在初始時所有樹的高度為0cm。每過去一天樹會自然成長1cm,每次樹被澆水後當天會額外成長1cm。m天中牛牛每天都都會選乙個區間[l,r]對這個區間內的樹進行澆水,牛牛想知道m天後有多少棵樹的高度為奇數,你能告訴牛牛嗎?
class solution ;
int ans = 0;
for(int i = 0; i < m; i++)
for(int i = 1; i <= n; i++)
for(int i = 1; i <= n; i++)
return ans;
}};
字首和 差分
數列的字首和 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 ...
字首和 差分
有n個數和q次操作,每一次操作指明了要操作的區間 l,r 以及讓該區間內的所有元素全部加c 輸出q次操作後所有元素的大小 第一行 n q 1 n,q 2 105 第二行 n個數 a1,a2 an 106 ai 106 接下來q 行 每行3個數 l r c 表示 l,r 區間內每個數加c 1 l r ...
字首和 差分
顧名思義 用某乙個陣列來記錄陣列a前i項和,這個還可以用來求區間 l,r 的和 s r s l 1 因為第l項也在區間內 話不多說,直接上例題 leetcode 5393 ac const int maxn 1e5 5 class solution int ans 0 for int i 0 i k...