BZOJ 1588 - 营业额统计 第一道splay..题目数据有误...

          数据有误,,,读入文件不完整...所以到后面会没有数可以读..无语了...真是奇葩...

          这道题线段树离线也可以做吧...我开始用treap做.结果超时了...splay还是强啊...代码..参考了几个大神的..haha593572013  、 胡浩大神


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1<<30
#define pi acos(-1.0)
#define MAXN 300015
using namespace std;  
struct Splay_tree
{  
      int key[MAXN],son[MAXN][2],pre[MAXN];
      int root,num;
      void initial()
      {
             root=num=pre[0]=son[0][0]=son[0][1]=0; 
             addnode(root,-oo);  
             addnode(son[root][1],oo);  
             pre[num]=root;
      }   
      void addnode(int &k,int c)
      {
             k=++num;
             key[k]=c,son[k][0]=son[k][1]=0;
      }
      void rot(int x,int tp)
      {  
             int y=pre[x];  
             son[y][!tp]=son[x][tp];  
             pre[son[x][tp]]=y;  
             pre[x]=pre[y];  
             if(pre[x]) son[pre[y]][son[pre[y]][1]==y]=x;  
             son[x][tp]=y;  
             pre[y]=x;   
      }  
      void splay(int x)
      { 
             while(pre[x])
             {  
                   if(!pre[pre[x]]) rot(x,son[pre[x]][0]==x);  
                   else   
                   {  
                         int y=pre[x],z=pre[y];  
                         int f=(son[z][0]==y);  
                         if(son[y][f]==x) rot(x,!f),rot(x,f);  
                                     else rot(y,f),rot(x,f);  
                   }  
             }   
             root=x;  
      }  
      void insert(int &k,int KEY,int father)
      {
             if (!k)
             {
                   addnode(k,KEY);
                   pre[k]=father; 
                   splay(k);
                   return;
             }
             if (KEY==key[k]) { splay(k);  return; }
             if (KEY<key[k])  insert(son[k][0],KEY,k);
                         else insert(son[k][1],KEY,k); 
      } 
      void findpre(int x,int c,int &ans)
      {  
             if (!x) return;  
             if(key[x]<=c)
             {  
                  ans=key[x];  
                  findpre(son[x][1],c,ans);  
             }else  
                  findpre(son[x][0],c,ans);  
      }  
      void findsucc(int x,int c,int &ans)
      {  
             if(!x) return ;  
             if(key[x]>=c) 
             {  
                  ans=key[x];  
                  findsucc(son[x][0],c,ans);  
             } else  
                  findsucc(son[x][1],c,ans);  
      }  
      int findans(int c)
      {
             int x,y;  
             findpre(root,c,x);  
             findsucc(root,c,y);  
             if(abs(x-c)<=abs(y-c))
             {
                   if(x!=-oo) return abs(x-c);  
             }
             else  
                   if(y!=oo) return abs(y-c);   
      }
}st;
int main()
{                
       int n,p,x,ans=0; 
       scanf("%d",&n);
       st.initial();
       scanf("%d",&x);
       st.insert(st.root,x,0); 
       ans=x;
       for (p=2;p<=n;p++)
       {
              while (scanf("%d",&x)==EOF) x=0; 
              ans+=st.findans(x); 
              st.insert(st.root,x,0);           
       }       
       printf("%d\n",ans);
       return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值