用途:主要用於給某一區間 加乙個數,或減乙個數 。o(1)的時間內完成
差分,實際上就是字首和的逆過程, 例如 已知字首和陣列 b, 那麼它的差分陣列 a
a1 = b1;
a2 = b2-b1;
a3 = b3-b2;
a4 = b4-b3;
an= bn-bn-1;
如果把它們相加就很容易看出: a1+a2+a3+a4+...an = bn;
1、此題說每次在某乙個區間【l,r】內加一或減一,如果暴力做的話時間複雜度是o(n)的,所以我們可以先離線出a陣列的差分陣列b
然後 b[l]++, b[r+1]--; 這樣我們就可以保證在l,r,之間的a陣列每乙個數都是加了1,的 然後 b[r+1]--,是使r之後的數消除這種加1的影響。
2、要使最後的數都一樣,那麼b陣列中的b2--->bn 一定全 0
因為 b2 = a2-a1;
b3 = a3-a2;
bn = an-an-1;
如果全0 的話, a1=a2=a3=....................=an
所以我們可以用貪心的思想,來使得b中所有數變成零。 我們知道我們在做 b[l]++, b[r+1]--;操作的時候,要找兩個數配對,那麼 負數++,正數--,是不是就最快了。 但是最終結果可能依然不是全 0 的,因為 abs(sum(正數)) 可能 != abs(sum(負數))
所以,我們可以 讓最後不等於0 的數全和 b1|| bn+1 來換。
所以 ans1 = min(pos,neg)+abs(pos-neg)
ans2 = abs(pos-neg)+1; /// 如果最後剩 3 -----> (0,3)(1,2)(,2,1)(,3,0) 這4種方案來選擇 b1還是 bn+1
#include#include#include#include#define ll long long
using namespace std;
const int n = 100010;
ll a[n];
int main()
for(int i=n;i>1;i--)
ll pos = 0 , neg = 0;
for(int i=2;i<=n;i++)
cout
}
藍書 100 IncDec序列
差分陣列的巧妙運用 讓所有數都相同即 讓差分陣列bi,b2 bn都等於0.每次操作相當於選擇i,j.bi bj 為了讓b2 bn都等於0 正數之和 p,負數之和q 最少操作次數一定是 先選擇一正一負,抵消,然後剩的全正或者全負,與b1 bn 1,進行操作。最少次數為 p q 由於選擇b1,bj 和b...
IncDec序列(差分 貪心)
原題鏈結 題目大意 給定乙個序列,可以在其連續子串行上進行加一或者減一操作,求使整個序列變成相同數的最小運算元和種數。思路首要要明確是對 l,r 序列進行加一或者減一操作,可以聯想到字首和,我們對乙個陣列b的第l項進行減一操作,第r 1項進行加一操作,這樣作用到b陣列的字首和序列就是連續的區間段 l...
IncDec序列 差分 貪心
給定乙個長度為 n 的數列 a1,a2,an 每次可以選擇乙個區間 l,r 使下標在這個區間內的數都加一或者都減一。求至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列可能有多少種。第一行輸入正整數n。接下來n行,每行輸入乙個整數,第i 1行的整數代表ai。第...