題意:
給出N天的營業額,定義某天營業額的“最小波動值”爲這天之前所有營業額與該天營業額之差的絕對值的最小值。特別地,第一天營業額的“最小波動值”即爲第一天營業額本身。
實質:給定一個序列
解法:
如果順序記下每天的營業額並使之有序的話,我們會發現,每加入一天的營業額,它的前驅和後繼與它差值之中小的一個即爲這一天的“最小波動值”,累加答案即可。
因此我們可以用BST維護營業額,每插入一個數就查詢前驅和後繼。但是在實踐中有一種編程複雜度更低,而效果很好的方法:用插入時走過的路徑上的所有點維護答案即可,正確性顯然。
(不要隨便看代碼。不要隨便看代碼。不要隨便看代碼。因爲很重要所以說三次。)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;
//Global Variables & Definitions
int N;
inline int iabs(int a) {
return a > 0 ? a : -a;
}
//End Global Variables & Definitions
//Treap
struct node {
node *ch[2];
int v;
int r;
node() : r(rand()) { ch[0] = ch[1] = NULL; }
node(int v) : v(v), r(rand()) { ch[0] = ch[1] = NULL; }
int cmp(int va) {
return va < this -> v ? 0 : 1;
}
};
void Rotate(node* & o, int d) {
node *k = o -> ch[d ^ 1];
o -> ch[d ^ 1] = k -> ch[d];
k -> ch[d] = o;
o = k;
}
int Insert(node* & o, int v) {
int t = iabs(v - o -> v), t2 = 0x7fffffff;
int d = o -> cmp(v);
if(o -> ch[d] == NULL) {
o -> ch[d] = new node(v);
} else {
t2 = Insert(o -> ch[d], v);
}
if(o -> r < o -> ch[d] -> r) Rotate(o, d ^ 1);
return min(t, t2);
}
//End Treap
//Main Structure
node *root;
inline void ir() {
//srand(time(NULL));
srand(20150423);
scanf("%d", &N);
}
int main() {
ir();
int ans = 0, temp;
//1st
if(!~scanf("%d", &temp)) temp = 0;
ans = temp;
root = new node(temp);
//else
for(int i = 1;i < N;++i) {
if(!~scanf("%d", &temp)) temp = 0;
ans += Insert(root, temp);
}
printf("%d\n", ans);
return 0;
}
在BZOJ上srand(time(NULL))奇怪的RE了,所以隨便指定了一個種子。
傲嬌的BZOJ又抽風