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;
}
posted @ 2019-09-12 22:33  Mystery_Sky  阅读(207)  评论(0编辑  收藏  举报