第一道splay,算是学会了最最基础的splay操作。
有一点要特别注意,就是一字型旋转的时候要先旋转y再旋x,这样复杂度降低很多。。。不要写成两次都旋转x。。。
总算是调试好了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int INF=1e9+10; const int maxn=1000100; int key[maxn],pre[maxn]; int ch[maxn][2]; int rt,tot; int n,x; void newnode(int &r,int fa,int k) { r=++tot; pre[r]=fa;key[r]=k; MS0(ch[r]); } void rot(int x,int kind) { int y=pre[x]; ch[y][kind^1]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; } void splay(int x,int goal) { while(pre[x]!=goal){ if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x); else{ int y=pre[x],z=pre[y]; int kind=ch[y][0]==x,one=0; if(ch[y][0]==x&&ch[z][0]==y) one=1; if(ch[y][1]==x&&ch[z][1]==y) one=1; if(one) rot(y,kind),rot(x,kind); else rot(x,kind),rot(x,kind^1); } } if(goal==0) rt=x; } int Insert(int x) { int u=rt,f=0; while(u){ if(key[u]==x){ splay(u,0); return 0; } f=u; u=ch[u][x>key[u]]; } newnode(ch[f][x>key[f]],f,x); splay(ch[f][x>key[f]],0); return 1; } int get_pre(int x) { if(!ch[x][0]) return -INF; x=ch[x][0]; while(ch[x][1]) x=ch[x][1]; return key[x]; } int get_next(int x) { if(!ch[x][1]) return INF; x=ch[x][1]; while(ch[x][0]) x=ch[x][0]; return key[x]; } void get(int u) { if(u==0) return; if(ch[u][0]) get(ch[u][0]); printf("u=%2d key=%2d lch=%2d rch=%2d fa=%2d ",u,key[u],ch[u][0],ch[u][1],pre[u]); if(ch[u][1]) get(ch[u][1]); } int main() { freopen("in.txt","r",stdin); while(cin>>n){ rt=tot=0;MS0(pre);MS0(ch); int ans=0; REP(i,1,n){ scanf("%d",&x); if(i==1){ ans+=x; newnode(rt,0,x); continue; } if(!Insert(x)) continue; int a=get_pre(rt),b=get_next(rt); //get(rt); ans+=min(abs(a-x),abs(b-x)); } cout<<ans<<endl; } return 0; }