[APIO2014]序列分割
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2014]序列分割相关的知识,希望对你有一定的参考价值。
斜率优化
f[i]=max(f[j]+s[j]*(s[i]-s[j]))
令g[i]=f[i]-s[i]^2
j比k优 那么g[j]+s[i]s[j]>g[k]+s[i][k]
g[j]-g[k]>s[i](s[k]-s[j])
g[j]-g[k]/(s[j]-s[k])<-s[i]
所以维护队列上凸即可
#include<iostream> #include<cstdio> #include<queue> #define MAXN 100000 #include<cstring> #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int n,k; int from[202][MAXN+5]; ll f[MAXN+5]; ll s[MAXN+5]; ll g[2][MAXN+5]; int q[MAXN+5]; int top=0,tail=1; ll get(int pre,int x,int t) { while(top-tail>=1&&(g[pre][q[tail]]-g[pre][q[tail+1]])<s[x]*(s[q[tail+1]]-s[q[tail]])) ++tail; from[t][x]=q[tail]; return g[pre][q[tail]]+s[q[tail]]*s[x]; }; void ins(int t,int k) { while(top-tail>=1) { int i=q[top-1],j=q[top]; if((g[t][k]-g[t][j])*(s[i]-s[j])<(g[t][j]-g[t][i])*(s[j]-s[k])) top--; else break; } q[++top]=k; } int main() { //freopen("sequence.in","r",stdin); //freopen("sequence.out","w",stdout); n=read();k=read(); for(int i=1;i<=n;i++) { s[i]=read();s[i]+=s[i-1]; } int pre=0,nown=1; for(int i=1;i<=n;i++) g[pre][i]=-(s[i]*s[i]); for(int l=2;l<=k+1;l++) { memset(f,0,sizeof(f));top=0;tail=1; memset(g[nown],0,sizeof(g[nown])); ins(pre,l-1); for(int i=l;i<=n;i++) { f[i]=get(pre,i,l); g[nown][i]=f[i]-(s[i]*s[i]); if(s[i]!=s[i-1])ins(pre,i); //printf("%d %d %d %I64d\n",l,i,from[l][i],f[i]); } nown=1-nown; pre=1-pre; } printf("%lld\n",f[n]); return 0; }
以上是关于[APIO2014]序列分割的主要内容,如果未能解决你的问题,请参考以下文章