2020 10 03日常總結 二分演算法(下)

2021-10-09 23:03:42 字數 3754 閱讀 9696

在昨天的部落格中,我們粗談了一下二分和一些零碎演算法的結合,今天我們講講二分和oi中另一類非常重要的演算法——dp的結合。

[problem]

\color}

[problem]

求可能的最小的最大間隔。

1 ≤n

≤5×1

04,1

≤m≤1

×109

1 \leq n \leq 5 \times 10^4,1 \leq m \leq 1 \times 10^9

1≤n≤5×

104,

1≤m≤

1×10

9。[solution]

\color}

[solution]

最大值最小,一看就想到二分答案。

二分答案 mid

\texttt

mid,表示最大間隔為 mid

\texttt

mid,看看是否可行。

設計乙個dp:記 fif_

fi​ 表示第 i

ii 個數必選時最小的權值和。

我們有如下的轉移:

f i=

min⁡i−

mid−1≤

j≤i+

ai

f_=\min\limits_-1 \leq j \leq i}\left \\right \}+a_i

fi​=i−

mid−1≤

j≤imin​+

ai​

直接轉移是 o(n

2)

o(n^2)

o(n2

) 的,必超時。仔細觀察可以發現,我們可以用單調佇列優化我們的dp,於是dp時間複雜度降為 o(n

)o(n)

o(n)

。總時間複雜度:o(n

×log⁡m

)o(n \times \log m)

o(n×

logm)。

[code]

\color}

[code]

const

int n=

5e4+

100;

int l,r,mid,ans,n,t;

int f[n]

,q[n]

,h,t,a[n]

;inline

bool

check

(int mid)

for(

int i=n-mid;i<=n;i++)if

(f[i]

<=t)

return

true

;return

false;}

intmain()

else l=mid+1;

}printf

("%d"

,ans)

;return0;

}

[problem]

\color}

[problem]

[solution]

\color}

[solution]

首先明確一點:當 r+g

≥n

r+g\geq n

r+g≥

n 時,答案為 1

11,因為我們可以對於每個法壇都用一次法杖。

明確這點有什麼用?有。一特判,二把 r,g

r,gr,

g 的範圍降到 1≤r

,g≤n

1\leq r,g \leq n

1≤r,g≤

n。答案明顯有單調性(可二分性),考慮二分答案。

二分答案 mid

\texttt

mid 表示判斷當 l

=mid

l=\texttt

l=mid 時是否可行。

記 p

ip_i

pi​ 表示在 a

ia_i

ai​ 位置使用一次第一根法杖最遠可以覆蓋到哪個法壇,同理 q

iq_i

qi​ 表示在 a

ia_i

ai​ 位置使用一次第二根法杖最遠可以覆蓋到哪個法壇。對是否熟悉的同學一讀這段話應該就可以知道:我們可以用尺取法在 o(n

)o(n)

o(n)

的時間複雜度內求出 pi,

qi

p_i,q_i

pi​,qi

​。特別地,為了方便處理,我們令 pn+

1=qn

+1=n

p_=q_=n

pn+1​=

qn+1

​=n。

記 f i,

jf_

fi,j

​ 表示使用 i

ii 次第一根法杖和 j

jj 次第二根法杖最多可以覆蓋到前幾個法壇,則有轉移方程:

f i,

j=

max⁡(p

fi−1

,j+1

,qfi

,j−1

+1

)f_=\max(p_+1},q_+1})

fi,j​=

max(pf

i−1,

j​+1

​,qf

i,j−

1​+1

​)轉移方程相當的簡單易懂。

初始對於 ∀i,

j\forall i,j

∀i,j

,都有 fi,

j=

0f_=0

fi,j​=

0 。最後如果 fr,

g=

nf_=n

fr,g​=

n 則 mid

\texttt

mid 可行,否則不可行。

時間複雜度:o(r

×g

×log⁡a

i)

o(r \times g \times \log a_)

o(r×g×

logai​

)。[code]

\color}

[code]

int r,g,n,a[

2010

],l,r,ans,mid;

int f[

2010][

2010

],p[

2010

],q[

2010];

inline

void

ckmax

(int

&a,int b)

inline

bool

check

(int mid)

p[n+1]

=q[n+1]

=n;//特判

for(

int i=

0;i<=r;i++

)for

(int j=

0;j<=g;j++

)return f[r]

[g]>=n;

}int

main()

l=1;r=a[n]

-a[1]+

1;while

(l<=r)

else l=mid+1;

}printf

("%d"

,ans)

;return0;

}

2019 08 18 日常總結

一本通1599 題意 在一年前贏得了小鎮的最佳草坪比賽後,fj 變得很懶,再也沒有修剪過草坪。現在,新一輪的最佳草坪比賽又開始了,fj 希望能夠再次奪冠。然而,fj 的草坪非常髒亂,因此,fj 只能夠讓他的奶牛來完成這項工作。fj 有 nn 只排成一排的奶牛,編號為 11 到 nn。每只奶牛的效率是...

5059日常總結

1.乙個函式的形參是const char 實參是可以是char 如果乙個函式的返回值是const char 不能用char 來接收返回值 2.為什麼沒有靜態的建構函式和析構函式?建構函式成員函式使用現有分配構造指定的物件 即存在this。static成員函式指定物件沒有儲存,因此沒有關聯的例項要構造...

2019 10 01日常總結

前言 今天是祖國母親70歲生日,請允許我向祖國母親說一聲 生日快樂!願您永遠繁榮昌盛 山清水秀!題意 松鼠的新家是一棵樹,前幾天剛剛裝修了新家,新家有n nn個房間,並且有n 1 n 1n 1根樹枝連線,每個房間都可以相互到達,且倆個房間之間的路線都是唯一的。天哪,他居然真的住在 樹 上。松鼠想邀請...