# 洛谷3648 [APIO2014]序列分割（斜率优化+dp）

qwq

$$a\ b\ c$$

$dp[i][p]=max(dp[j][p-1]+(sum[i] + sum[j])\times sum[j])$

$$f[x]=dp[x]-sum[x]*sum[x]$$

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk make_pair
#define ll long long
using namespace std;
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 1e5+1e2;
struct Point
{
ll x,y;
int num;
};
ll chacheng(Point x,Point y)
{
return x.x*y.y-x.y*y.x;
}
bool count(Point i,Point j,Point k)
{
Point x,y;
x.x=k.x-i.x;
x.y=k.y-i.y;
y.x=k.x-j.x;
y.y=k.y-j.y;
if (chacheng(x,y)>=0) return true;
return false;
}
struct Node{
Point q[maxn];
void push(Point x)
{
q[++tail]=x;
}
void pop(int lim)
{
}
};
Node q[210];
ll sum[maxn];
int n,k;
ll dp[2][210];
int pos[100010][210];
int main()
{
k++;
for (int i=1;i<=n;i++) sum[i]+=sum[i-1];
q[0].push((Point){0,0,0});
for (int i=1;i<=n;i++)
{
for (int j=1;j<=min(i,k);j++)
{
q[j-1].pop((-1)*sum[i]);
dp[i&1][j]=now.y+now.x*now.x+(sum[i]-now.x)*now.x;
pos[i][j]=now.num;
q[j].push((Point){sum[i],dp[i&1][j]-sum[i]*sum[i],i});
}
}
cout<<dp[n&1][k]<<endl;
for (int i=n,j=k;i && j>1;i=pos[i][j],j--)
cout<<pos[i][j]<<" ";
cout<<endl;
return 0;
}


posted @ 2018-12-27 17:01  y_immortal  阅读(148)  评论(0编辑  收藏  举报