蓝题训练9.24P3648 [APIO2014] 序列分割

P3648 [APIO2014] 序列分割
Tag: 略
题意:略

题解:斜率优化

参考代码
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll maxn=100010;
ll f[2][maxn],pre[210][maxn];
ll head,tail,n,k,a[maxn];
struct vec{
	ll id,x,y;
	ll operator()(ll v){
		return x*v+y;
	}
}q[maxn];
ll cross(vec a,vec b,vec c){
	a.x-=b.x;a.y-=b.y;
	b.x-=c.x;b.y-=c.y;
	return b.x*a.y-b.y*a.x;
}
void solve(){
	cin>>n>>k;
	for(int i=1;i<=n;i++) {
		cin>>a[i];
		a[i]+=a[i-1];
	}
	for(int t=1;t<=k;t++){
		head=tail=0;
		q[0]={0,0,0};
		for(int i=1;i<=n;i++){
			while(head<tail&&q[head](a[i])<=q[head+1](a[i])){
				++head;
			}
			f[t&1][i]=q[head](a[i]);
			pre[t][i]=q[head].id;
			vec x={i,a[i],f[t&1^1][i]-a[i]*a[i]};
			while(head<tail&&cross(q[tail-1],q[tail],x)<=0){
				--tail;
			}
			q[++tail]=x;
		}
	}
	cout<<f[k&1][n]<<"\n";
	ll now=n;
	for(int i=k;i>=1;i--){
		cout<<pre[i][now]<<' ';
		now=pre[i][now];
	}
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	ll T=1;
	while(T--) solve();
}



posted @ 2026-10-26 15:06  pigeon666  阅读(3)  评论(0)    收藏  举报