[HNOI2002]营业额统计 Splay tree

  Splay tree入门题,学好代码风格,学习HH大牛的,传送门。。

  1 #include <functional>
  2 #include <algorithm>
  3 #include <iostream>
  4 //#include <ext/rope>
  5 #include <fstream>
  6 #include <sstream>
  7 #include <iomanip>
  8 #include <numeric>
  9 #include <cstring>
 10 #include <cassert>
 11 #include <cstdio>
 12 #include <string>
 13 #include <vector>
 14 #include <bitset>
 15 #include <queue>
 16 #include <stack>
 17 #include <cmath>
 18 #include <ctime>
 19 #include <list>
 20 #include <set>
 21 #include <map>
 22 using namespace std;
 23 //using namespace __gnu_cxx;
 24 //define
 25 #define pii pair<int,int>
 26 #define mem(a,b) memset(a,b,sizeof(a))
 27 #define lson l,mid,rt<<1
 28 #define rson mid+1,r,rt<<1|1
 29 #define PI acos(-1.0)
 30 //typedef
 31 typedef long long LL;
 32 typedef unsigned long long ULL;
 33 //const
 34 const int N=100005;
 35 const int INF=0x3f3f3f3f;
 36 const int MOD=100000,STA=8000010;
 37 const LL LNF=1LL<<60;
 38 const double EPS=1e-8;
 39 const double OO=1e15;
 40 const int dx[4]={-1,0,1,0};
 41 const int dy[4]={0,1,0,-1};
 42 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
 43 //Daily Use ...
 44 inline int sign(double x){return (x>EPS)-(x<-EPS);}
 45 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
 46 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
 47 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
 48 template<class T> inline T Min(T a,T b){return a<b?a:b;}
 49 template<class T> inline T Max(T a,T b){return a>b?a:b;}
 50 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
 51 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
 52 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
 53 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
 54 //End
 55 
 56 int pre[N],key[N],ch[N][2],root,tot;  //分别表示父结点,键值,左右孩子(0为左孩子,1为右孩子),根结点,结点数量
 57 int n;
 58 //新建一个结点
 59 void addn(int &r,int fa,int k)
 60 {
 61     r=++tot;
 62     pre[r]=fa;
 63     key[r]=k;
 64     ch[r][0]=ch[r][1]=0;  //左右孩子为空
 65 }
 66 //旋转,kind为1为右旋,kind为0为左旋
 67 int Rotate(int x,int kind)
 68 {
 69     int y=pre[x],z=pre[y];
 70     //类似SBT,要把其中一个分支先给父节点
 71     ch[y][!kind]=ch[x][kind];
 72     pre[ch[x][kind]]=y;
 73     //如果父节点不是根结点,则要和父节点的父节点连接起来
 74     if(z)ch[z][ch[z][1]==y]=x;
 75     pre[x]=z;
 76     ch[x][kind]=y;
 77     pre[y]=x;
 78 }
 79 //Splay调整,将根为r的子树调整为goal
 80 int Splay(int r,int goal)
 81 {
 82     int y,kind;
 83     while(pre[r]!=goal){
 84         //父节点即是目标位置,goal为0表示,父节点就是根结点
 85         y=pre[r];
 86         if(pre[y]==goal){
 87             Rotate(r,ch[y][0]==r);
 88         }
 89         else {
 90             kind=ch[pre[y]][0]==y;
 91             //两个方向不同,则先左旋再右旋
 92             if(ch[y][kind]==r){
 93                 Rotate(r,!kind);
 94                 Rotate(r,kind);
 95             }
 96             //两个方向相同,相同方向连续两次
 97             else {
 98                 Rotate(y,kind);
 99                 Rotate(r,kind);
100             }
101         }
102     }
103     //更新根结点
104     if(goal==0)root=r;
105 }
106 
107 int Insert(int k)
108 {
109     int r=root;
110     while(ch[r][k>key[r]]){
111         //不重复插入
112         if(key[r]==k){
113             Splay(r,0);
114             return 0;
115         }
116         r=ch[r][k>key[r]];
117     }
118     addn(ch[r][k>key[r]],r,k);
119     //将新插入的结点更新至根结点
120     Splay(ch[r][k>key[r]],0);
121     return 1;
122 }
123 //找前驱,即左子树的最右结点
124 int getpre(int x)
125 {
126     if(!ch[x][0])return -INF;
127     x=ch[x][0];
128     while(ch[x][1])x=ch[x][1];
129     return key[x];
130 }
131 //找后继,即右子树的最左结点
132 int getsuf(int x)
133 {
134     if(!ch[x][1])return INF;
135     x=ch[x][1];
136     while(ch[x][0])x=ch[x][0];
137     return key[x];
138 }
139 
140 int main()
141 {
142  //   freopen("in.txt","r",stdin);
143     int i,a,ans;
144     while(~scanf("%d",&n))
145     {
146         ans=root=tot=0;
147         for(i=0;i<n;i++){
148             if(scanf("%d",&a)==EOF)a=0;
149             if(i==0){
150                 ans+=a;
151                 addn(root,0,a);
152             }
153             else {
154                 if(Insert(a)==0)continue;
155                 ans+=Min(a-getpre(root),getsuf(root)-a);
156             }
157         }
158         printf("%d
",ans);
159     }
160     return 0;
161 }
原文地址:https://www.cnblogs.com/zhsl/p/3189912.html