傳送門
首先容易證明,得分和切的順序沒有關係
所以直接預設先切左邊再切右邊就好了
然後顯然可以 $dp$
一開始想的是設 $f[i][j]$ 表示切了 $i$ 次,此次把 $j$ 和 $j+1$ 分開,得到的最大價值
那麼顯然列舉上一次切的位置 $k$ ,那麼 $f[i][j]=f[i-1][k]+(sum[j]-sum[k])(sum[n]-sum[j])$
這個東西是可以斜率優化+滾動陣列,但是很不好寫,一堆邊界問題要想,**就不放了(親自嘗試發現甚至會爆$long\ long$)
另乙個好的思路:設 $f[i][j]$ 表示已經切了 $i$ 次,只考慮前面 $j$ 塊的最大價值
同樣列舉 $k$,$f[i][j]=f[i-1][k]+(sum[i]-sum[j])*sum[j]$
這樣式子就好化了:$f[i][j]=f[i-1][k]+sum[i]sum[j]-sum[j]^2$
:$-sum[i]sum[j]+f[i][j]=f[i-1][k]-sum[j]^2$
那麼 $k=-sum[i],x=sum[j],b=f[i][j],y=f[i-1][k]-sum[j]^2$
發現 $k,x$ 都單調,所以直接斜率優化就好了,同樣要滾動陣列
注意原序列可能有 $0$,那麼 $x$ 就不是單調上公升而是單調不增,求斜率時要注意特判 $x$ 相同的情況!
#include#include#include
#include
#include
#include
using
namespace
std;
typedef
long
long
ll;typedef
long
double
ldb;
inline
intread()
while(ch>='
0'&&ch<='
9')
return x*f;
}const
int n=1e5+7
;int
n,m;
ll sum[n],f[
2][n];
inline ll x(
int x)
inline ll y(
int x)
inline ldb slope(
int i,int
j)int
q[n],l,r;
intmain()
swap(f[
0],f[1
]); }
printf(
"%lld\n
",f[1
][n]);
return0;
}
P3648 APIO2014 序列分割
part1 首先看到題目,嗯 o o很騷 手玩一波樣例之後發現狀態很好想 這裡簡單地任務階段可以被劃分次數 也就是劃分順序 和劃分位置來劃分 初步想法是 f i j 表示前 i 次最後一次切的是 j 位置 隨後意識到沒法通過上一層進行轉移,這裡出現問題也是正常,因為沒有進行更深入地發掘性質 此處無法...
P3648 APIO2014 序列分割 斜率優化
好的先把自己的式子推了出來 樸素 定義 f i j 表示前 i 個數進行 j 次切割的最大得分,s i 為字首和 那麼轉移方程為 f i j max f i 1 j s j s i s j 優化一下 省掉第一維 f i max mem j s j s i s j f j mem j 相當於 f i ...
Luogu 3648 APIO2014 序列分割
題目鏈結 首先要發現乙個重要的性質 分割的順序是不會影響答案的 證明 首先對於沒有交的兩段區間,顯然先後順序改變不會有影響 而對於在同一段區間上的兩次分割 設有一段序列由長度為 x,y,z 的三段拼接起來 如果先分割 xy 和 z 再分割 x 和 y 答案是 x y z x y 而如果先分割 x 和...