3675: [Apio2014] sequence split time limit:40 Sec Memory limit:128 MB
submit:1420 solved:583
[Submit] [Status] [Discuss] Description Little H has recently been fascinated by a separate sequence of games. In this game, small h needs to divide a series of non-negative integers of length n into k+1 non-empty subsequence sequences. In order to get the k+1 subsequence, the small H needs to repeat the following steps of K: 1. Small h first selects a sequence longer than 1 (at the beginning of the small h only a sequence of length n-that is, the entire sequence obtained at the beginning) ; 2. Select a location and divide the sequence into successive two non-empty new sequences through this position. After each of these steps, small h will get a certain score. This fraction is the product of the elements and in two new sequences. Small h wants to choose the best way to divide, so that after K-wheel, the total score of small h is the largest. Input
Enter the first line containing two integers n,k (k+1≤n).
The second line contains n nonnegative integers a1,a2,...,an (0≤ai≤10^4), which represents the sequence at the beginning of the small H obtained. Output
The output first line contains an integer, which is the maximum fraction that can be obtained for small H.
Sample Input7 3
4 1 3 4 0 2 3
Sample Output108
HINT
"Sample description"
In the example, small H can get 108 points with the following 3-wheel operation:
1. -Start small H has a sequence (4,1,3,4,0,2,3). Small H selects the position after the 1th number
Divide the sequence into two parts and get the 4x (1+3+4+0+2+3) =52 points.
2. At the beginning of this round, small H has two sequences: (4), (1,3,4,0,2,3). Small h selection in 3rd number
The position after the word divides the second sequence into two parts and gets (1+3) x (4+0+2+3) =36 points.
3. At the beginning of this round, small H has three sequences: (4), (1,3), (4,0,2,3). Small h selection in 5th
The position after the number divides the third sequence into two parts and gets (4+0) x (2+3) =20 points.
After the three-wheeled operation, the small H will get four sub-sequences: (4), (1,3), (4,0), (2,3) and a total of 52+36+20=108 points.
"Data size and rating":
Data meets 2≤n≤100000,1≤k≤min (N-1,200).
SourceSolution
Personal feeling compare God's question
First you need to find a property:
Cut k times, as long as the correct position is cut, then the answer is not the order of the cut
Prove:
In general, suppose a string is $abcd$, if it is to be split into $a|b|cd$ then:
First split into $ab|cd$ the current answer is $a*cd+b*cd$, and then split into $a|b|cd$, the answer is $a*b+a*cd+b*cd$
First split into $a|bcd$ the current answer is $a*bcd$, split into $a|b|cd$, the answer is $a*bcd+b*cd$
Then the two-way can be found to be the same. So, for the rest is also appropriate;
Then a preliminary transfer can be drawn :
$f [I][j]=max (f[j][k-1]+sum[j]* (Sum[i]-sum[j])) $ where $f[i][j]$ represents: the first I element, divided into the maximum fraction of the K segment
Then you can do the slope optimization, the final formula: $ (dp[j '][k]-dp[i '][k]+sum[i ']*sum[i ']-sum[j ']*sum[j '])/(Sum[i ']-sum[j ']) <=sum[i]$
There's an extra deal if $a[i]==0$ then it actually doesn't make sense and instead hinders the calculation, then you can throw it directly
The memory is a bit small, need to scroll the array, then roll it.
Code
#include <iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespaceStd;inlineintRead () {intx=0, f=1;CharCh=GetChar (); while(ch<'0'|| Ch>'9') {if(ch=='-') f=-1; Ch=GetChar ();} while(ch>='0'&& ch<='9') {x=x*Ten+ch-'0'; Ch=GetChar ();} returnx*F;}#defineMAXN 100010#defineMAXK 201intN,k,a[maxn],que[maxn],l,r;Long Longsum[maxn],dp[maxn][2];inlineDoubleSlopeintIintJintk) { return Double(Dp[j][k]-dp[i][k]+sum[i]*sum[i]-sum[j]*sum[j])/Double(sum[i]-sum[j]);}intMain () {n=read (), k=read (); for(intI=1; i<=n; i++) {A[i]=read (); if(a[i]==0) {i--; n--;Continue;} Sum[i]=sum[i-1]+A[i]; } for(intj=1, k=1; k<=k; k++,j^=1, l=r=0) for(intTmp,i=k; i<=n; i++) { while(L<r && Slope (que[l],que[l+1],j^1) <=sum[i]) l++; TMP=Que[l]; DP[I][J]=dp[tmp][j^1]+ (Sum[i]-sum[tmp]) *Sum[tmp]; while(L<r && Slope (que[r-1],que[r],j^1) >=slope (que[r],i,j^1)) r--; que[++r]=i; } printf ("%lld\n",dp[n][k&1]); return 0;}
WA several times ... It's been a long qaq.
"BZOJ-3675" sequence split DP + slope optimization