[CSP2019] division problem-solving report

[CSP2019] divided

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;
}

Guess you like

Origin www.cnblogs.com/brucew-07/p/11896792.html