序列分割[斜率優化]
阿新 • • 發佈:2018-12-09
可以證明選的順序對答案沒有影響
於是有轉移方程
變形得到
我們令
另外 , 寫之前最好畫圖考慮細節
最大值維護上凸包,斜率是負數 , 所以圖大概是這樣
然後樹形結合來寫
#include<bits/stdc++.h> #define N 100050 #define M 205 #define y(k,x) (f[x][k-1]-s[x]*s[x]) #define LL long long using namespace std; LL f[N][M]; int from[N][M]; int n,k,val[N],q[N]; LL s[N]; double K(int now,int i,int j){ if(s[i]==s[j]) return 1e18; return (y(now,j)-y(now,i))*1.0/(s[j]-s[i])*1.0; } void dfs(int i,int j){ if(j==0) return; i=from[i][j]; printf("%d ",i); dfs(i,j-1); } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&val[i]); s[i]=(LL)s[i-1]+val[i]; } for(int i=1;i<=k;i++){ int l=1,r=0; for(int j=1;j<=n;j++){ while(l<r && K(i,q[l],q[l+1]) >= -s[j]) l++; f[j][i] = f[q[l]][i-1] + (LL)s[q[l]] * (s[j]-s[q[l]]); from[j][i] = q[l]; while(l<r && K(i,q[r],j) >= K(i,q[r-1],q[r])) r--; q[++r] = j; } }printf("%lld\n",f[n][k]); dfs(n,k); return 0; }