P3648 APIO2014 序列分割 斜率優化

2022-03-30 07:06:28 字數 1120 閱讀 9958

好的先把自己的式子推了出來:

樸素:定義\(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-1][j]\)

換成斜率優化的式子:

\(mem[j]-s[j]^2=-s[i]*s[j]+f[i]\)

求\(f[i]\)最大值,所以維護上凸包;斜率\(-s[i]\)單調遞減,所以乙個單調佇列維護凸包。

然後康了一眼別人的題解:維護下凸包?

???黑人問號.jpg

後來發現自己就是個傻子:自己的是對的,只不過斜率那裡和他們的相比少乘了個\(-1\)

\(ou\)。。那就沒事了

(所以我寫的還是自己的)

#include#include#include#define r register int

#define ll long long

using namespace std;

namespace luitaryi const int n=100010;

int n,k,h,t,q[n],pre[210][n];

ll f[n],mem[n],s[n];

inline int x(int i)

inline ll y(int i)

inline double k(int i,int j)

inline void main() {

g(n),g(k); for(r i=1,x;i<=n;++i) g(x),s[i]=s[i-1]+x;

for(r i=1;i<=k;++i) { h=t=0;

for(r j=1;j<=n;++j) {

while(h=-s[j]) ++h;

f[j]=mem[q[h]]+1ll*s[q[h]]*s[j]-1ll*s[q[h]]*s[q[h]];

pre[i][j]=q[h];

while(h2019.08.17

83

P3648 APIO2014 序列分割

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

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...

Luogu 3648 APIO2014 序列分割

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