演算法競賽高階指南 Inc序列

2021-09-10 02:19:43 字數 2427 閱讀 7677

給定乙個長度為 n 的數列 a1,a2,…,an,每次可以選擇乙個區間 [l,r],使下標在這個區間內的數都加一或者都減一。

求至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列可能有多少種。

第一行輸入正整數n。

接下來n行,每行輸入乙個整數,第i+1行的整數代表ai。

第一行輸出最少操作次數。

第二行輸出最終能得到多少種結果。041

1221

2差分:與字首和互逆

設原陣列為a[1

],a[

2]…a

[n

]a[1],a[2]…a[n]

a[1],a

[2]…

a[n]

定義差分b[i

]=a[

i]−a

[i−1

],b[

1]=a

[1

]b[i] = a[i] - a[i-1], b[1] = a[1]

b[i]=a

[i]−

a[i−

1],b

[1]=

a[1]有a[

i]=b

[1]+

b[2]

+…+b

[i

]a[i] = b[1] + b[2] + … + b[i]

a[i]=b

[1]+

b[2]

+…+b

[i]即,若b為陣列a的差分序列,則a是b的字首和序列

和字首和類似,差分的作用是把區間操作變為單點操作。

思路:因為只是+1,-1,所以不需要線段樹或樹狀陣列

本題要求讓陣列a全相同,可以轉化為所有數的差分為0

解題步驟:

對原陣列a1…an求差分序列b1…bn

如果要給區間[l,r] 加 c ,可以通過對查分陣列進行b[l] += cb[r+1] -= c兩步單點操作實現。

此後當我們再求原陣列時,因為原陣列是差分序列的字首和,在求a[0]…a[l-1]時,因為差分b[0]…b[l-1]都沒變,所以a[0]…a[l-1]也沒變。

在求a[l]…a[r]時,因為差分b[l] += c,所以a[l]…a[r]都加了c。

在求a[r+1]…a[n]時,因為差分b[l]+=c,b[r]-=c,所以a[r+1]…a[n]沒變。

總結: 對陣列中乙個區間的加c與減c,可以轉換為區間端點的差分加c與減c。

對於本題:如果可以經過n次運算使差分序列全部變為0,則陣列也可以通過這n次運算變為相同的數。

如陣列a: 1 1 2 2 1

其差分b:(1)0 1 0 -1

要讓a[3]…a[4]這段區間(差分的字首和)減1,使其全部元素相等,

等價於讓b[3]-=1, b[5] +=1即可。

進一步考慮,b[3]原本是正數,b[5]原本是負數。

我們的最終目的是讓b陣列的每個數都變為0,我們的每次操作最多可以讓b陣列的兩個數乙個+1,乙個-1。(這兩個數分別是區間的兩個端點,可以任意選)。 這裡的最多是因為也可以只讓1個數+1或-1。基於貪心的思想,我們會先將正數與負數相抵消,最後剩下只有正數或只有負數的時候再單獨處理正數與負數。

第一問:每次最多只能同時把差分陣列b的乙個數+1,乙個數-1, 問把pos個+1和neg個-1都變為0需要幾步。

最小步數:min

(pos

,neg

)+ab

s(po

s−ne

g)

min(pos, neg) + abs(pos - neg)

min(po

s,ne

g)+a

bs(p

os−n

eg)

第二問 :最終得到的數列可能有多少種

有a bs

(pos

−neg

)+

1abs(pos - neg) + 1

abs(po

s−ne

g)+1

種匹配方式

#include

#include

using namespace std;

typedef

long

long ll;

const

int n =

100010

;int a[n]

;int

main()

cout <<

min(pos, neg)

+abs

(pos - neg)

<< endl;

cout <<

abs(pos - neg)+1

<< endl;

return0;

}

《演算法競賽高階指南》 防曬

有c頭奶牛進行日光浴,第i頭奶牛需要minspf i 到maxspf i 單位強度之間的陽光。每頭奶牛在日光浴前必須塗防曬霜,防曬霜有l種,塗上第i種之後,身體接收到的陽光強度就會穩定為spf i 第i種防曬霜有cover i 瓶。求最多可以滿足多少頭奶牛進行日光浴。輸入格式 第一行輸入整數c和l。...

《演算法競賽高階指南》蚯蚓

蛐蛐國最近蚯蚓成災了!隔壁跳蚤國的跳蚤也拿蚯蚓們沒辦法,蛐蛐國王只好去請神刀手來幫他們消滅蚯蚓。蛐蛐國裡現在共有 n 只蚯蚓,第 i 只蚯蚓的長度為 ai 所有蚯蚓的長度都是非負整數,即可能存在長度為0的蚯蚓。每一秒,神刀手會在所有的蚯蚓中,準確地找到最長的那乙隻,將其切成兩段。若有多隻最長的,則任...

演算法競賽高階指南筆記

原碼 原碼就是符號位加上真值的絕對值,即用第一位表示符號,其餘位表示值.比如如果是8位二進位制 其中,第一位為1是負數 1 0000 0001 原 1 1000 0001 原 因此,8位二進位制數的取值範圍 127,127 補碼正數的補碼是其本身 負數的補碼是在其原碼的基礎上,符號位不變,其餘各位取...