营业额统计

https://loj.ac/problem/10143

题目描述

  给出一个\(n\)个数的数列,定义\(f_i=min\{|a_i-a_j|\}(i\ge j)\),求\(\sum f_i\)

思路

  题目就要我们求在这个数之前并且和这个数的差最小的数,我们考虑这个数必定出现在当前\(a_i\)的前驱或后继中。所以我们可以用平衡树维护这个数列,每次求一下前驱和后继,注意这里可以相等,再把原数插入进去即可。

代码

#include<bits/stdc++.h>
using namespace std;

int read()
{
	int res=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*w;
}

const int INF=0x3f3f3f3f;
const int N=1e6+10;
#define root t[0].son[1]
struct Splay
{
	struct Node
	{
		int val,siz,son[2],fa,cnt;
		void init(int x,int f)
		{
			son[0]=son[1];
			siz=cnt=1;
			val=x;fa=f;
		}
	}t[N];
	int tot;
	int ident(int x){return t[t[x].fa].son[0]==x?0:1;}
	void change(int x,int f,int o){t[x].fa=f;t[f].son[o]=x;}
	void pushup(int x){t[x].siz=t[t[x].son[0]].siz+t[t[x].son[1]].siz+t[x].cnt;}
	void rotate(int x)
	{
		int y=t[x].fa,z=t[y].fa;
		int yson=ident(x),zson=ident(y);
		change(t[x].son[yson^1],y,yson);
		change(y,x,yson^1);
		change(x,z,zson);
		pushup(y);pushup(x);
	}
	void splay(int x,int goal)
	{
		goal=t[goal].fa;
		while(t[x].fa!=goal)
		{
			int y=t[x].fa;
			if(t[y].fa==goal)rotate(x);
			else if(ident(x)==ident(y))rotate(y),rotate(x);
			else rotate(x),rotate(x);	
		}
	}
	void insert(int x)
	{
		int now=root;
		if(root==0){t[++tot].init(x,0);root=tot;}
		else while(1)
		{
			t[now].siz++;
			if(t[now].val==x){t[now].cnt++;splay(now,root);}
			int nxt=x<t[now].val?0:1;
			if(!t[now].son[nxt])
			{
				t[++tot].init(x,now);
				t[now].son[nxt]=tot;
				splay(tot,root);
				return ;
			}
			now=t[now].son[nxt];
		}
	}
	int querynxt(int x)
	{
		int now=root,ans=INF;
		while(now)
		{
			if(t[now].val>=x)ans=min(ans,t[now].val);
			int nxt=t[now].val>x?0:1;
			now=t[now].son[nxt];
		}
		return ans;
	}
	int querypre(int x)
	{
		int now=root,ans=-INF;
		while(now)
		{
			if(t[now].val<=x)ans=max(ans,t[now].val);
			int nxt=t[now].val>x?0:1;
			now=t[now].son[nxt];
		}
		return ans;
	}
}T;

int main()
{
	int n=read();
	int x=read(),ans=x;
	T.insert(x);
	for(int i=1;i<n;i++)
	{
		x=read();
		int a=T.querypre(x),b=T.querynxt(x);
		ans+=min(abs(x-a),abs(x-b));
//		cout<<a<<' '<<b<<endl;
//		cout<<"ans="<<ans<<endl;
		T.insert(x);
	}
	printf("%d",ans);
}
posted @ 2019-11-06 20:06  fbz  阅读(285)  评论(0编辑  收藏  举报