zoukankan      html  css  js  c++  java
  • 营业额统计

    https://loj.ac/problem/10143

    题目描述

      给出一个(n)个数的数列,定义(f_i=min{|a_i-a_j|}(ige 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);
    }
    
  • 相关阅读:
    剑指 Offer 55
    剑指 Offer 55
    剑指 Offer 22. 链表中倒数第k个节点
    剑指 Offer 29. 顺时针打印矩阵
    剑指 Offer 17. 打印从1到最大的n位数
    剑指 Offer 57
    剑指 Offer 59
    B. Han Solo and Lazer Gun 暴力 水
    C. Number of Ways 思维
    C. Destroying Array 并查集/线段树 Intel Code Challenge Elimination Round (Div. 1 + Div. 2, combined)
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11808305.html
Copyright © 2011-2022 走看看