Time Limit: 3 Seconds Memory Limit: 65536 KB
Bernard Madoff is an American former stock broker, investment adviser, non-executive chairman of the NASDAQ stock market, and the admitted operator of what has been described as the largest Ponzi scheme in history.
Two programmers, Jerome O'Hara and George Perez, who helped Bernard Madoff program to produce false records have been indicted. They were accused of conspiracy, falsifying records of a broker dealer and falsifying records of an investment adviser.
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.
Input
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.
Output
For each test case, print a single line that contains minimal possible risk value.
Sample Input
4 300 400 200 100 0
Sample Output
400
我地做浙大月赛果阵既一个题目,后来听101majia讲系用左偏树。
我之前研究堆果阵都有睇过下左偏树,其实就系二叉堆加上一个限制条件令到成个堆左偏,吾难理解。制定一个甘样既规则可以讲剩系得一个好处,合并快。尼条题既思路我系参照一个国家训练队关于左偏树既论文编写既,呢篇论文讲左偏树同埋例题证明既时候都唔错,但系讲到例题实现既时候,有两点令我捻左好耐。
一、点解输入既时候要dec(nd[i].key, i)?
二、点解要合并两个奇数堆既时候先删除堆顶元素?
第一个问题,其实尼条题目吾需要,因为答案系非严格递增,第二个问题我真系未明白点解,睇黎系维护中位数既关键。
其实睇左分析之后发觉尼条题目其实唔一定要用左偏树,因为数据结构唔要求动态,而且稳区间中位数即系稳区间第n/2大数,我地可以用划分、归并树代替。
下面贴上代码~
2608269 | 2011-07-31 15:45:34 | Accepted | 3512 | C++ | 280 | 968 | SGetEternal-_- |
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
#define MAXI 50011
struct LTT
{
struct node
{
int l, r, key, dis;
}t[MAXI];
void clear(int n)
{
int i;
for (i = 0; i <= n; i++)
t[i].l = t[i].r = t[i].dis = -1;
}
int merge(int x, int y)
{
if (x == -1) return y;
if (y == -1) return x;
if (t[x].key < t[y].key)
swap(x, y);
t[x].r = merge(t[x].r, y);
if (t[t[x].l].dis < t[t[x].r].dis)
swap(t[x].l, t[x].r);
t[x].dis = t[t[x].r].dis + 1;
return x;
}
int delet(int x)
{
return merge(t[x].l, t[x].r);
}
}zkl;
int main()
{
int n, i, j, k, pid[MAXI], tid[MAXI];
long long tsu;
while (scanf("%d", &n), n)
{
zkl.clear(n);
pid[0] = tid[0] = 0;
for (i = j = 1; i <= n; i++, j++)
{
scanf("%d", &zkl.t[i].key);
pid[j] = tid[j] = i;
while (j > 1 && zkl.t[tid[j - 1]].key > zkl.t[tid[j]].key)
{
--j;
tid[j] = zkl.merge(tid[j], tid[j + 1]);
if (((pid[j + 1] - pid[j]) % 2 == 1 && (pid[j] - pid[j - 1]) % 2 == 1))
tid[j] = zkl.delet(tid[j]);
pid[j] = pid[j + 1];
}
}
for (tsu = 0, i = 1; i < j; i++)
for (k = pid[i - 1] + 1; k <= pid[i]; k++)
tsu += abs(zkl.t[k].key - zkl.t[tid[i]].key);
cout << tsu << endl;
}
return 0;
}
尼条题目我地一开始仲以为同菲波那契有关,因为个题目名有Fin