bzoj4831 DP 貪心 序列操作

2021-09-07 19:42:21 字數 3417 閱讀 6948

description

給定乙個長度為 n 的非負整數序列 a_1,a_2,…a_n 。你可以使用一種操作:選擇在序列中連續的兩個正整數,

並使它們分別減一。當你不能繼續操作時遊戲結束,而你的得分等於你使用的操作次數。你的任務是計算可能的最小 得分和最大得分。

input

第一行包含乙個正整數 t ,表示有 t 組資料,滿足 t ≤ 200 。 接下來依次給出每組測試資料。對於每組測試資料:

第一行包含乙個正整數 n ,滿足 1 ≤ n ≤ 10^5 。 第二行包含 n 個非負整數,表示 a_1,a_2,…a_n ,滿足

σa_i ≤ 10^6 。 約 5 組資料滿足 n ≥ 10^3 或 σa_i ≥ 10^4 。

output

對於每組測試資料 輸出一行兩個非負整數,用乙個空格隔開,前者表示可能的最小得分,後者表示可能的最大得分。

sample input

1 2 1 3

1 2 1 1 3

sample output

2 2

2 3

題解

感覺官方題解的做法好勁啊…

提供乙個超越官方的做法…

首先最大值不難想到是直接從左往右掃一遍,能減就減

考慮最小值怎麼做

設乙個dp[

i]

dp[i]

dp[i

]表示把i

ii變為0

00且i

ii前面沒有相鄰非0

00位的最小值

我們要保證a[i

]a[i]

a[i]

和a [i

−1

]a[i-1]

a[i−1]

有乙個等於0

00的話就兩種轉移

1:( i,

i−1)

(i,i-1)

(i,i−1

)視為一組,根據定義直接將a[i

]a[i]

a[i]

變為0

00,此時直接加上dp[

i−2]

dp[i-2]

dp[i−2

]的貢獻即可

2:( i,

i−1,

i−2)

(i,i-1,i-2)

(i,i−1

,i−2

)視為一組,分類討論情況

當a [i

−1

]>a[

i]

a[i-1]>a[i]

a[i−1]

>a[

i]時,可以直接加上a[i

−1

]a[i-1]

a[i−1]

的貢獻,因為如果a[i

−2]+

a[i]

i−1]

a[i-2]+a[i]a[

i−2]

+a[i

]i−1]

時這樣不合法但是由於不優秀所以不會被取到,會被第一種方案乾掉

當a [i

−1

]<=a

[i

]a[i-1]<=a[i]

a[i−1]

<=a

[i] 時,直接加上a[i

]a[i]

a[i]

的貢獻,顯然這時候a[i

−1

]a[i-1]

a[i−1]

會變為0

00且符合定義a[i

]=

0a[i]=0

a[i]=0

故轉移為

d p[

i]=m

in(d

p[i−

2]+a

[i],

dp[i

−3]+

max(

a[i−

1],a

[i])

)dp[i]=min(dp[i-2]+a[i],dp[i-3]+max(a[i-1],a[i]))

dp[i]=

min(

dp[i

−2]+

a[i]

,dp[

i−3]

+max

(a[i

−1],

a[i]

))複雜度就是超級優秀的o(n

)o(n)

o(n)

了,和∑a[

i]

\sum a[i]

∑a[i

]無關…

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define mp(x,y) make_pair(x,y)

#define pll pair

#define pii pair

using

namespace std;

inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}int stack[20]

;inline

void

write

(ll x)if(

!x)int top=0;

while

(x)stack[

++top]

=x%10

,x/=10;

while

(top)

putchar

(stack[top--]+

'0');}

inline

void

pr1(

int x)

inline

void

pr2(ll x)

const

int maxn=

100005

;int n,a[maxn]

,dp[maxn]

;int

main()

printf

("%d %d\n"

,min

(dp[n]

,dp[n-1]

),ans);}

return0;

}

BZOJ 1046 上公升序列(DP)

time limit 10 sec memory limit 162 mb submit 4898 solved 1704 submit status discuss 對於乙個給定的s 若有p 滿足 x1 x2 xm 且 ax1 ax 2 axm 那麼就稱p為s的乙個上公升序列。如果有多個p滿足條件...

bzoj1345 序列問題 貪心

對於乙個給定的序列a1,an,我們對它進行乙個操作reduce i 該操作將數列中的元素ai和ai 1用乙個元素max ai,ai 1 替代,這樣得到乙個比原來序列短的新序列。這一操作的代價是max ai,ai 1 進行n 1次該操作後,可以得到乙個長度為1的序列。我們的任務是計算代價最小的redu...

nssl1488 上公升子串行 貪心,dp

長度為n nn的序列,分割成兩個上公升子串行要求長度差最小 我們對於i ai a ji iai aj 的點之間連邊,然後可以對於乙個聯通塊進行二分圖染色,我們可以發現,如果我們先固定乙個點的顏色,那麼這個聯通塊的二分圖染色方案數為1或0。之後兩個聯通塊互不影響,所以我們可以用dpdp dp來計算方案...