In every quarter of these years, the two programmers would receive a data sheet, which provided a series of profit records a1 a2 ... aN in that period. Due to the economic crisis, the awful records might scare investors away. Therefore, the programmers were asked to falsifying these records into b1 b2 ... bN. In order to deceive investors, any record must be no less than all the records before it (it means for any 1 ≤ i < j ≤ N, bi ≤ bj).
On the other hand, they defined a risk value for their illegal work: risk value = | a1 - b1 | + | a2 - b2 | + ... + | aN - bN | . For example, the original profit records are 300 400 200 100. If they choose 300 400 400 400 as the fake records, the risk value is 0 + 0 + 200 + 300 = 500. But if they choose 250 250 250 250 as the fake records, the risk value is 50 + 150 + 50 + 150 = 400. To avoid raising suspicion, they need to minimize the risk value.
Now we will give you some copies of the original profit records, you need to find out the minimal possible risk value.
There are multiple test cases (no more than 20).
For each test case, the first line contains one integer N (1 ≤ N ≤ 50000), the next line contains N integers a1 a2 ... aN (-109 ≤ ai ≤ 109). The input will end with N = 0.
For each test case, print a single line that contains minimal possible risk value.
4 300 400 200 100 0
400
//
http://blog.csdn.net/king821221/article/details/2068668
假设我们已经找到前k个数a[1], a[2], … , a[k] (k
#include
#include
#include
#include
using namespace std;
//给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列
//{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| + |a2 - b2| + … + |an - bn| 最小。
const int N=51000;
const int DEEP=20;//划分树最多层数
struct Node
{
int l,r;
};
Node tree[N*4];//线段树
int data[N];//数据
int seg[DEEP][N];//划分树
int LessMid[DEEP][N];//表示在[L,R]内有几个数小于等于date[mid]
void buildtree(int root,int l,int r,int d)//节点,左右区间,层数
{
tree[root].l=l,tree[root].r=r;
if(l==r) return ;//叶子节点
int mid=(l+r)>>1;
int lsame=mid-l+1;//左面最多可放几个与data[mid]相同的数
for(int i=l;i<=r;i++)//得出实际能放几个相同的数
{
if(seg[d][i] }
int tl=l,tr=mid+1,same=0;//划分树 ,tl,tr表示数的左右子树的起点
for(int i=l;i<=r;i++)
{
if(i==l) LessMid[d][i]=0;//表示在[L,R]内有几个数小于等于date[mid]
else LessMid[d][i]=LessMid[d][i-1];
if(seg[d][i] else if(seg[d][i]>data[mid]) seg[d+1][tr++]=seg[d][i];//划分到右子树
else //相等情况
{
if(same
}
}
buildtree(root<<1,l,mid,d+1);
buildtree((root<<1)+1,mid+1,r,d+1);
}
//查询[l,r]中的第k小数
int Query(int root,int l,int r,int d,int cnt)//节点,要查询的区间,层数,第cnt小数
{
if(l==r) return seg[d][l];
int s;//表示在[l,r]中有几个小于等于data[mid]的个数
int ss;//表示在[tree[root].l,l-1]中有几个小于等于data[mid]的个数
if(l==tree[root].l) s=LessMid[d][r],ss=0;
else s=LessMid[d][r]-LessMid[d][l-1],ss=LessMid[d][l-1];
if(s>=cnt) return Query(root<<1,tree[root].l+ss,tree[root].l+ss+s-1,d+1,cnt);
else
{
int mid=(tree[root].l+tree[root].r)>>1;
int bb=l-tree[root].l-ss;//表示[tree[root].l,l-1]中有多少个分到右面
int b=r-l+1-s;//表示[l,r]有多少个分到右面
return Query((root<<1)+1,mid+bb+1,mid+bb+b,d+1,cnt-s);
}
}
int a[N];//data
Node range[N];//分为几段
int mid[N];//每段中位数
int teg;
int _abs(int x)
{
return x>0?x:-x;
}
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
data[i]=a[i];
seg[1][i]=data[i];
}
sort(data+1,data+1+n);
buildtree(1,1,n,1);
teg=0;
for(int i=1;i<=n;i++)
{
range[++teg].l=i,range[teg].r=i;mid[teg]=a[i];
for(int j=teg;j>1;j--)
{
if(mid[j]
int l=range[j-1].l,r=range[j].r;
range[--teg].l=l,range[teg].r=r;
int k=(r-l)/2+1;
int tmp=Query(1,l,r,1,k);
mid[teg]=tmp;
}
else break;
}
}
long long cnt=0;
for(int i=1;i<=teg;i++)
{
for(int j=range[i].l;j<=range[i].r;j++)
{
cnt+=(long long)_abs(a[j]-mid[i]);
}
}
cout<
return 0;
}
/*
3
3 2 1
*/