题目大意:
给出公司N天的营业额Ai,每天的最小波动值为当天营业额与前面的营业额最小的差,问N天的最小波动值的总和为多少。 给 出 公 司 N 天 的 营 业 额 A i , 每 天 的 最 小 波 动 值 为 当 天 营 业 额 与 前 面 的 营 业 额 最 小 的 差 , 问 N 天 的 最 小 波 动 值 的 总 和 为 多 少 。
N<=32767
N
<=
32767
Ai<=1,000,000
A
i
<=
1
,
000
,
000
最后结果T<=231
最
后
结
果
T
<=
2
3
1
分析:
直接构造一颗treap每次求前驱,后继即可
注意前驱跟后继要考虑相同数的情况
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 23333333
#define N 100005
using namespace std;
struct Treap {
int l, r, dat, val, cnt;
} a[N];
int tot, root, n;
int New(int val) {
a[++tot].val = val;
a[tot].dat = rand();
a[tot].cnt = 1;
return tot;
}
void Build() {
New(-INF); New(INF);
root = 1;
a[root].r = 2;
}
void zig(int &p) {
int q = a[p].l;
a[p].l = a[q].r;
a[q].r = p;
p = q;
}
void zag(int &p) {
int q = a[p].r;
a[p].r = a[q].l;
a[q].l = p;
p = q;
}
void Insert(int &p, int val) {
if (p == 0) {
p = New(val);
return;
}
if (val == a[p].val) {
a[p].cnt++;
return;
}
if (val < a[p].val) {
Insert(a[p].l, val);
if (a[p].dat < a[a[p].l].dat) zig(p);
}
else {
Insert(a[p].r, val);
if (a[p].dat < a[a[p].r].dat) zag(p);
}
}
int GetPre(int val) {
int ans = 1;
int p = root;
while (p) {
if (val == a[p].val) {
ans = p;
break;
}
if (a[p].val < val && a[p].val > a[ans].val) ans = p;
p = val < a[p].val ? a[p].l : a[p].r;
}
return a[ans].val;
}
int GetNext(int val) {
int ans = 2;
int p = root;
while (p) {
if (val == a[p].val) {
ans = p;
break;
}
if (a[p].val > val && a[p].val < a[ans].val) ans = p;
p = val < a[p].val ? a[p].l : a[p].r;
}
return a[ans].val;
}
int main() {
Build();
scanf("%d", &n);
int ans = 0, x;
for (int i = 1; i <= n; i++) {
scanf("%d", &x);
int a = GetPre(x);
int b = GetNext(x);
Insert(root, x);
if (i != 1) ans += min(x - a, b - x);
else ans += x;
}
printf("%d\n", ans);
}