码迷,mamicode.com
首页 > Windows程序 > 详细

[APIO2014]序列分割

时间:2019-06-14 18:32:11      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:code   splay   scanf   scan   eset   open   none   double   min   

题目


用这题来复习下斜率优化(跟新学的差不多

 要想斜率优化你得现有dp式(不然优化个p

这道题简单分析后可以得到一个简单的dp式

设$Fi,j$表示前1~i分成$j$段的最大值(分析可知顺序无关

$si$为1~i的和,则有

$F_{i,k}? = max \left \{ F_{j,k−1}?+s_j?(s_i?−s_j?) \right \}$ $(0 \leq j<)$

吼,现在我们有了dp式

接下来我们得有个大小关系

我们任取j,k满足 $0k<j<i$ 且 j 比 k 更优,那么有如下不等式:

$g_j+s_j(s_i-s_j)\ge g_k+s_k(s_i-s_k)$

$\frac{(g_j-{s_j}^2)-(g_k-{s_k}^2)}{s_k-s_j}\leq s_i$

有了这样一个式子再简单画个图推导一下可知需要维护的是个下凸包

怎么说呢总感觉写的有点敷衍233

技术图片
 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 #define ll long long
 4 using namespace std;
 5 int n,k,a[N],q[N],l,r,pre[N][205];
 6 ll s[N],f[N],g[N];
 7 double slope(int j,int k){
 8     if(s[j]==s[k])return -1e10;
 9     return (double)((g[j]-s[j]*s[j])-(g[k]-s[k]*s[k]))/(s[k]-s[j]);
10 }
11 int main(){
12     scanf("%d%d",&n,&k);
13     for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]+a[i];
14     for(int t=1;t<=k;t++){
15         int l=1,r=0;
16         q[++r]=0;
17         for(int i=1;i<=n;i++){
18             while(l<r&&slope(q[l],q[l+1])<=s[i])l++;
19             f[i]=g[q[l]]+(s[i]-s[q[l]])*s[q[l]];
20             pre[i][t]=q[l];
21             while(l<r&&slope(q[r],i)<=slope(q[r-1],q[r]))r--;
22             q[++r]=i;
23         }
24         memcpy(g,f,sizeof(f));
25     }
26     printf("%lld\n",f[n]);
27     int x=pre[n][k];
28     printf("%d",x);
29     for(int i=k-1;i>=1;i--){
30         x=pre[x][i];
31         printf(" %d",x);
32     }
33     return 0;
34 }
View Code

 

[APIO2014]序列分割

标签:code   splay   scanf   scan   eset   open   none   double   min   

原文地址:https://www.cnblogs.com/2017SSY/p/11012146.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!