BZOJ - 4518: 征途(斜率优化,求N数划分为M区间的最小方差)
注意初始化。。。等等补
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=3010; int q[maxn],head,tail; ll s[maxn],s2[maxn],dp[maxn][maxn]; ll getans(int i,int j,int k){ return dp[i-1][k]+(s[j]-s[k])*(s[j]-s[k]); } double dy(int i,int x,int y){ return ((double)(dp[i][x]+s2[x]-dp[i][y]-s2[y]))/(double)(s[x]-s[y]); } int main() { int N,M,i,j; scanf("%d%d",&N,&M); memset(dp,0x3f,sizeof(dp)); dp[0][0]=0; //初始化,避免出现i>j的情况 for(i=1;i<=N;i++) scanf("%lld",&s[i]),s[i]+=s[i-1],s2[i]=s[i]*s[i]; for(i=1;i<=M;i++){ head=tail=0; for(j=1;j<=N;j++){ while(head<tail&&getans(i,j,q[head])>getans(i,j,q[head+1])) head++; while(head<tail&&dy(i-1,j,q[tail])<dy(i-1,q[tail],q[tail-1])) tail--; q[++tail]=j; dp[i][j]=getans(i,j,q[head]); } } printf("%lld\n",dp[M][N]*M-s2[N]); return 0; }
It is your time to fight!