P4072-[SDOI2016] 征途
P4072 [SDOI2016] 征途
Description
把一些数据分组,使得每组方差和最小。
Solution
设方差和为
设
我们考虑斜率优化 dp
。
拆开式子有
则有
由于
我们考虑开一个双端队列,每次对于一个新的
由于每个点最多只能被作为答案或者删除一次,所以这个复杂度是
复杂度
Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m;
int sum[N];
int qu[N];
int f[N],g[N];
double X(int i){
return -2*sum[i];
}
double Y(int i){
return g[i]+sum[i]*sum[i];
}
double check(int x,int y){
return ((Y(x)-Y(y))/(X(x)-X(y)));
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int temp;scanf("%d",&temp);sum[i]=sum[i-1]+temp;
g[i]=sum[i]*sum[i];
}
for(int k=1;k<m;k++){
int hd=1,tl=1;
qu[1]=k;
for(int i=k+1;i<=n;i++){
while(hd<tl&&check(qu[hd],qu[hd+1])> -sum[i]) ++hd;
int ans=qu[hd];
f[i]=g[ans]+(sum[i]-sum[ans])*(sum[i]-sum[ans]);
while(hd<tl&&check(qu[tl],qu[tl-1])<check(qu[tl],i)) --tl;
qu[++tl]=i;
// printf("%d %d %d %lf\n",ans,i,f[i],check(2,3));
}
for(int i=1;i<=n;i++) g[i]=f[i];
}
printf("%d",-sum[n]*sum[n]+m*f[n]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】