The meaning of problems
There \ (n-\) non-negative integers \ (a_i \) \ ((n-\. 4 * 10 ^ Le. 7) \) , divide them into several parts, referred to as \ (S_i \) , requires \ (S_ { . 1} + I \ GE S_i \) ,
provided \ (RES = \ sum_ {I} = ^ {K}. 1 S_i ^ 2 \) .
demand \ (RES \) minimum
Thinking
64 pts
Written exam on the practice.
Set \ (f [i] [j ] \) is the starting point for the first segment \ (I \) , end point \ (J \) when \ (RES \) minimum.
Naive approach enumerated directly \ (I , J, K \) , the \ (f [i] [j ] \) from \ (f [j] [k ] \) transfer over.
Optimization:
Consider the intermediate transfer point \ (J \) , for each \ (I <J \) , legal \ (K \) range is increasing, it is possible to enumerate only \ (i, j \) then pointer \ (K \) The \ (sum_j-sum_ {i- 1} \) continuously forgotten forward, and the minimum value can be updated.
88 pts
There are provided \ (K \) blocks, two properties can be obtained.
Nature. 1 : \ (K \) , the more preferred embodiment.
Perceptual appreciated: \ (A + B ^ 2 ^ 2 \ Le (A + B) ^ 2 \) .
further inferred
properties 2 : \ (S_k \) smaller the preferred embodiment.
perceptual appreciated: \ (S_k \) is smaller, in order to make a legitimate program, forcing the front to the \ (S \ ) should be as small as possible, since \ (a \) non-negative integer, (S \) \ smaller value, \ (K \) greater, more preferably 1 according to the nature of the program.
So that we can maintain a monotonous queue for each one, to find when it is the end point, the smallest \ (S_k \) .
When new elements are added to the queue as well as some of the monotonous details, see the code.
100pts
The above approach to add a high-precision (High precision such things have long forgotten, okay ...)
Code
64pts
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e3+7;
const ll inf=5e18;
int n,ty;
ll a[N],sum[N],f[N][N],ans=inf;
void read(){ }
ll p2(ll x){ return x*x; }
int main(){
//freopen("divd.in","r",stdin);
cin>>n>>ty;
if(ty) read();
else for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; }
memset(f,127,sizeof(f));
for(int i=1;i<=n;i++) f[i][n]=p2(sum[n]-sum[i-1]);
for(int j=n;j>=1;j--){
int k=n;
ll minx=inf;
for(int i=1;i<=j;i++){
while(p2(sum[j]-sum[i-1])<=p2(sum[k]-sum[j])){
minx=min(minx,f[j+1][k]);
k--;
}
f[i][j]=min(f[i][j],minx+p2(sum[j]-sum[i-1]));
}
}
for(int i=1;i<=n;i++) ans=min(ans,f[1][i]);
printf("%lld\n",ans);
return 0;
}
88pts
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=4e7+7;
int n,ty,pre[N],que[N],t1,t2;
ll a[N],sum[N],lst[N],ans;
void read(){};
ll p2(ll x){ return x*x; }
int main(){
// freopen("divd.in","r",stdin);
// freopen("x.out","w",stdout);
cin>>n>>ty;
if(ty) read();
else for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; }
t1=t2=1;
que[1]=0;
for(int i=1;i<=n;i++){
// printf("%d: ",i); for(int j=t1;j<=t2;j++) printf("%d ",que[j]); putchar('\n');
while(t1<t2&&lst[que[t1+1]]<=sum[i]-sum[que[t1+1]]) t1++;
pre[i]=que[t1];
lst[i]=sum[i]-sum[pre[i]];
while(t2>=t1&&lst[que[t2]]>=lst[i]+sum[i]-sum[que[t2]]) t2--;
que[++t2]=i;
}
int p=n;
while(p){
ans+=lst[p]*lst[p];
p=pre[p];
}
// for(int i=1;i<=n;i++) printf("pre[%d]: %d\n",i,pre[i]);
printf("%lld\n",ans);
return 0;
}