Given a sequence of length n \ (\ {a_i \} \) , which is divided into K consecutive segments, wherein a period for \ ([L, R & lt] \) , where the number of bits set to m, which define weights is \ (\ sum_ {I} = L ^ R & lt | m-a_i | \) , find the minimum sum of weights, \ (n-\ Leq 2000, K \ Leq 25 \) .
solution
Obviously disposed \ (F [i] [j] \) represents the number of i is divided into a front minimum weight and segment j, set \ (m (i, j) \) of \ (i \ j SIM \) of as for some of the weight, so there
\[f[i][j]=\min_{0\leq k<i}\{f[k][j-1]+m(k+1,i)\}\]
Border: \ (F [0] [0] = 0 \) , the remaining infinity
The answer: \ (f [the n-] [K] \)
Noting time complexity \ (2000 ^ 2 \ ^ 10 = 25. 8 Times \) , of one hundred million, can be too dangerous, quickly find the key is a binary function m, for the sake of m needs to address is dynamically maintained a sequence of intermediate the large number of apparently median position is increasing, consider double piles top optimization is not difficult to learn for the sequence \ (b_1, b_2, ..., b_p \) in terms of the median set to \ (b_q \) , then the value of the right to
\[\sum_{i=1}^p|b_i-b_q|=|b_p-b_q|+...+|b_q-b_q|+...+|b_q-b_1|=\]
\[=b_p-b_q+..+b_q-b_q+...+b_q-b_1=(b_p+...+b_{q+1})-(b_q+...+b_1)+qb_q-(p-q)b_q=\]
\[\sum_{i=q+1}^pb_i-\sum_{i=1}^qb_i+(2q-p)b_q\]
So for weight, as long as we can maintain such a formula, follow these steps
- Enumeration left point i, set large root heap is H, E is a small heap root
- Initialization \ (m (I, I) = 0, K = -a_i \) , was added H \ (a_i \)
- Enumeration right point j
- If \ (a_j \ Leq H.top () \) , then the \ (E.push (H.top ()) , H.pop (), k + = E.top () \ times 2, H.push (a_j ), k- = a_j \)
- Otherwise \ (E.push (a_j), k + = a_j \)
- If \ (i-j + 1 \ ) is even, then \ (H.push (E.top ()) , E.pop (), k- = H.top () \ times 2 \)
- Counted answer \ (m (i, j) = k + (2q-p) \ times H.top () \)
Reference Code:
#include <iostream>
#include <cstdio>
#include <queue>
#include <functional>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int a[2001],m[2001][2001],dp[2001][26];
priority_queue<int,vector<int>,less<int> >H;
priority_queue<int,vector<int>,greater<int> >E;
il void read(int&);
int main(){
int n,K;
while(read(n),read(K),n&&K){
for(int i(1);i<=n;++i)read(a[i]);
for(int i(1),j,k;i<=n;++i){
while(H.size())H.pop();
while(E.size())E.pop();
H.push(a[i]),k=-a[i];
for(j=i+1;j<=n;++j){
if(a[j]<=H.top())
E.push(H.top()),H.pop(),H.push(a[j]),
k-=a[j],k+=E.top()<<1;
else E.push(a[j]),k+=a[j];
if((j-i+1)&1)k-=E.top()<<1,H.push(E.top()),E.pop();
m[i][j]=k+H.top()*((H.size()<<1)-(j-i+1));
}
}memset(dp,2,sizeof(dp)),dp[0][0]=0;
for(int i,j(1),k;j<=K;++j)
for(i=j;i<=n;++i)
for(k=0;k<i;++k)
if(dp[i][j]>dp[k][j-1]+m[k+1][i])
dp[i][j]=dp[k][j-1]+m[k+1][i];
printf("%d\n",dp[n][K]);
}
return 0;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c==' '||c=='\n'||c=='\r');
ri bool check(false);if(c=='-')check|=true,c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
if(check)x=-x;
}