洛谷 3648 APIO2014 序列分割

2021-09-29 06:41:37 字數 2098 閱讀 9497

題目描述

你正在玩乙個關於長度為 n 的非負整數序列的遊戲。這個遊戲中你需要把序列分成 k+1 個非空的塊。為了得到 k+1 塊,你需要重複下面的操作 k 次:

選擇乙個有超過乙個元素的塊(初始時你只有一塊,即整個序列)

選擇兩個相鄰元素把這個塊從中間分開,得到兩個非空的塊。

每次操作後你將獲得那兩個新產生的塊的元素和的乘積的分數。你想要最大化最後的總得分。

輸入格式

第一行包含兩個整數 n 和 k。保證 k+1≤n。

第二行包含 n 個非負整數 a1,

a2,⋯

,a

na_1, a_2, \cdots, a_n

a1​,a2

​,⋯,

an​(0≤

ai≤1

04

)(0≤ai≤10^4)

(0≤ai≤

104)

,表示前文所述的序列。

輸出格式

第一行輸出你能獲得的最大總得分。

第二行輸出 k 個介於 1 到 n - 1 之間的整數,表示為了使得總得分最大,你每次操作中分開兩個塊的位置。第 i 個整數 s

is_i

si​​ 表示第 i 次操作將在 s

is_i

si​​ 和 si+

1s_

si+1

​ 之間把塊分開。

如果有多種方案使得總得分最大,輸出任意一種方案即可。

輸入輸出樣例

輸入 #1

7 34 1 3 4 0 2 3

輸出 #1

1081 3 5

說明/提示

2 ≤n

≤100000,1

≤k≤m

in

⁡2≤n≤100000,1≤k≤min⁡\

2≤n≤10

0000

,1≤k

≤min

解釋:dp[

k][i

]:

dp[k][i]:

dp[k][

i]:在i出化第k刀的最大值,則dp[

k][i

]=ma

xdp[k][i]=max\

dp[k][

i]=m

ax我們列舉k,進行斜率優化就可以了,老套路

設j

>

kj>k

j>

k,且j

jj優於k

kk,則最後可以化得(dp

[j]−

dp[k

])/(

sum[

j]−s

um[k

])

>su

m[n]

−sum

[i

](dp[j]-dp[k])/(sum[j]-sum[k])>sum[n]-sum[i]

(dp[j]

−dp[

k])/

(sum

[j]−

sum[

k])>su

m[n]

−sum

[i],然後套斜率優化模板就好了。注意0要單獨處理掉,0不會對答案最貢獻,但可以出現斜率不存在的情況。

#include#include#define ll long long

#define n 100004

using namespace std;

int n=0,k=0;

ll sum[n]=;

int q[n]=;

ll dp[203][n]=;

int front[203][n]=;

int ans[203]=;

int temp[n]=;

int t=0;

double cal(int x,int y,int k)

int main()

}n=t;t=0;

for(int i=1;i<=k;i++)

P3648 APIO2014 序列分割

part1 首先看到題目,嗯 o o很騷 手玩一波樣例之後發現狀態很好想 這裡簡單地任務階段可以被劃分次數 也就是劃分順序 和劃分位置來劃分 初步想法是 f i j 表示前 i 次最後一次切的是 j 位置 隨後意識到沒法通過上一層進行轉移,這裡出現問題也是正常,因為沒有進行更深入地發掘性質 此處無法...

Luogu 3648 APIO2014 序列分割

題目鏈結 首先要發現乙個重要的性質 分割的順序是不會影響答案的 證明 首先對於沒有交的兩段區間,顯然先後順序改變不會有影響 而對於在同一段區間上的兩次分割 設有一段序列由長度為 x,y,z 的三段拼接起來 如果先分割 xy 和 z 再分割 x 和 y 答案是 x y z x y 而如果先分割 x 和...

P3648 APIO2014 序列分割

傳送門 首先容易證明,得分和切的順序沒有關係 所以直接預設先切左邊再切右邊就好了 然後顯然可以 dp 一開始想的是設 f i j 表示切了 i 次,此次把 j 和 j 1 分開,得到的最大價值 那麼顯然列舉上一次切的位置 k 那麼 f i j f i 1 k sum j sum k sum n su...