Problem:
Score : 500 points

Problem Statement

There are N children standing in a line from left to right. The activeness of the i-th child from the left is A_i.

You can rearrange these children just one time in any order you like.

When a child who originally occupies the x-th position from the left in the line moves to the y-th position from the left, that child earns A_x \times |x-y| happiness points.

Find the maximum total happiness points the children can earn.

Constraints

2 \leq N \leq 2000

1 \leq A_i \leq 10^9

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_N

Output

Print the maximum total happiness points the children can earn.

Sample Input 1

4
1 3 4 2

Sample Output 1

20

If we move the 1-st child from the left to the 3-rd position from the left, the 2-nd child to the 4-th position, the 3-rd child to the 1-st position, and the 4-th child to the 2-nd position, the children earns 1 \times |1-3|+3 \times |2-4|+4 \times |3-1|+2 \times |4-2|=20 happiness points in total.

Sample Input 2

6
5 5 6 1 1 1

Sample Output 2

58

Sample Input 3

6
8 6 9 1 2 1

Sample Output 3

85

Solution in C (GCC 9.2.1) (judge verdict: Accepted)

#include <malloc.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//abc163E

void swap(long long *a, long long *b) {
  long long temp=*a;
  *a=*b, *b=temp;
}

void QuickSort(long long A[], long long B[], long long left, long long right) { //クイックソート//
  int Left=left, Right=right, pivot=A[(left + right) / 2];
  while(1){ // ソーティング
    while(A[Left] < pivot)
      Left++; // 基準より小さい値を左から見つけていく
    while(pivot < A[Right])
      Right--; // 基準より大きい値を右から見つけていく
    if(Left >= Right) break; // 見つかった値の順序が逆になったら終了
    swap(&A[Left], &A[Right]); // 値を交換
    swap(&B[Left], &B[Right]);
    Left++, Right--; // 次の値に移動
  }
  if(left < Left - 1) QuickSort(A, B, left, Left - 1); //左群を対象として再帰
  if(Right + 1 < right) QuickSort(A, B, Right + 1, right); //右群を対象として再帰
}

int main(void) {
  long long n, k, i, cou=0, tmp;
  long long mod=1000000007, happy=0, dpl, dpr, dpmax=0;
  scanf(" %lld", &n);
  long long a[n], ax[n], b[n];
  long long dp[n + 1][n + 1]; //dp[左寄せの数][同右]
  for(i=0; i < n; i++){
    scanf(" %lld", &a[i]);
    ax[i]=a[i], b[i]=i;
  }
  QuickSort(a, b, 0, n - 1);

  dp[1][0]=a[n - 1] * b[n - 1], dp[0][1]=a[n - 1] * (n - 1 - b[n - 1]);
  //printf("dp[1][0]=%lld\n", dp[1][0]);
  //printf("dp[0][1]=%lld\n", dp[0][1]);
  for(i=2; i <= n; i++){
    for(k=0; k <= i; k++){
      if(k == 0) dp[i][0]=dp[i - 1][0] + abs(i - b[n - i]-1) * a[n - i];
      else if(k == i) dp[0][i]=dp[0][i - 1] + abs(n - i - b[n - i]) * a[n - i];
      else{
        dpl=dp[i - k - 1][k] + abs(i - k - 1 - b[n - i]) * a[n - i];
        dpr=dp[i - k][k-1] + abs(n - k - b[n - i]) * a[n - i];
        //printf(" dpl=%lld+%d*%d=%d\n dpr=%lld+%d*%d=%d\n",
        //    dp[i - k - 1][k] ,abs(i - k - 1 - b[n - i]), a[n - i],dpl,
        //    dp[i - k][k - 1] ,abs(n - k  - b[n - i]), a[n - i], dpr);
        if(dpl > dpr) dp[i - k][k]=dpl;
        else dp[i - k][k]=dpr;
      }
      //printf("dp[%d][%d]=%lld\n", i - k, k, dp[i - k][k]);
    }

  }
  for(i=0; i <= n; i++)
    if(dpmax < dp[i][n - i]) dpmax=dp[i][n - i];

  printf("%lld", dpmax);
  return 0;
}