P2234 [HNOI2002]营业额统计
题面传送门
题意:对于N天的营业额,你需要求出每天营业额与当天前的营业额差值的最小值的和。
思路:感觉挺裸的SBT,对于每天的营业额x,插值,求x与x的前驱的差值d1,求x的后继与x的差值d2(ps:这里的前驱后继的可以等于x),用一个treap就可以过了。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
//Mystery_Sky
//
#define M 1000100
#define INF 0x3f3f3f3f
#define ll long long
inline int read()
{
int x = 0,f=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
struct Treap{
int size, cnt;
int l, r;
int dat, val;
}a[M];
int tot, root, n, ans;
inline int New(int val)
{
a[++tot].val = val;
a[tot].dat = rand();
a[tot].cnt = a[tot].size = 1;
return tot;
}
inline void update(int p)
{
a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
}
inline void build()
{
root = New(-INF);
a[root].r = New(INF);
update(root);
}
inline void right_Rotate(int &p)
{
int k = a[p].l;
a[p].l = a[k].r, a[k].r = p, p = k;
update(a[p].r);
update(p);
}
inline void left_Rotate(int &p)
{
int k = a[p].r;
a[p].r = a[k].l, a[k].l = p, p = k;
update(a[p].l);
update(p);
}
void insert(int &p, int val)
{
if(!p) {
p = New(val);
return;
}
if(val == a[p].val) {
a[p].cnt++;
update(p);
return;
}
else if(val < a[p].val) {
insert(a[p].l, val);
if(a[p].dat < a[a[p].l].dat) right_Rotate(p);
}
else {
insert(a[p].r, val);
if(a[p].dat > a[a[p].r].dat) left_Rotate(p);
}
update(p);
}
int query_pre(int val)
{
int ans = a[root].val;
int p = root;
while(p) {
if(a[p].val == val && a[p].cnt > 1) return val;
if(a[p].val < val) ans = a[p].val, p = a[p].r;
else p = a[p].l;
}
return ans;
}
inline int query_next(int val)
{
int ans = a[root].val;
int p = root;
while(p) {
if(a[p].val == val && a[p].cnt > 1) return val;
if(a[p].val > val) ans = a[p].val, p = a[p].l;
else p = a[p].r;
}
return ans;
}
int main() {
n = read();
build();
for(int i = 1; i <= n; i++) {
int x = read();
if(i == 1) ans += x, insert(root, x);
else {
insert(root, x);
int d1 = abs(x - query_pre(x));
int d2 = abs(query_next(x) - x);
//printf("%d %d\n", d1, d2);
ans += min(d1, d2);
}
}
printf("%d\n", ans);
return 0;
}
唯愿,青春不辜负梦想,未来星辰闪耀