HYSBZ - 1588 splay
阿新 • • 發佈:2017-10-19
void min article rtp closed sky 搜索 log 通過
題意:每天給你一個數,要求統計最小波動值,強制在線的就是每次從已經出現過的數值中找與當前值間隔最小的加起來
題解:splay維護,同時求解當前值的前驅和後繼,找距離小的那個就好了
splay是一種二叉搜索樹,可以在log(n)的時間內維護,而且通過左旋和右旋避免二叉搜索樹退化成一條鏈,而且可以利用二叉搜索樹性質方便的查找前驅和後繼
推薦博客
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #defineView CodeC 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 20090717 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=50000+10,maxn=60000+10,inf=0x3f3f3f; int rightson[N],leftson[N],father[N],value[N]; ll ans; bool f;int tot,n,root; void right_rotate(int x) { int y=father[x],z=father[y]; leftson[y]=rightson[x]; if(rightson[x]!=-1)father[rightson[x]]=y; father[x]=z; if(z!=-1) { if(leftson[z]==y)leftson[z]=x; else rightson[z]=x; } father[y]=x;rightson[x]=y; }void left_rotate(int x) { int y=father[x],z=father[y]; rightson[y]=leftson[x]; if(leftson[x]!=-1)father[leftson[x]]=y; father[x]=z; if(z!=-1) { if(leftson[z]==y)leftson[z]=x; else rightson[z]=x; } father[y]=x;leftson[x]=y; } void splay(int x)//一直旋轉到x成為root { // cout<<x<<"-----------"<<endl; while(father[x]!=-1) { // cout<<x<<" "<<father[x]<<endl; int y=father[x],z=father[y]; if(z==-1) { if(rightson[y]==x)left_rotate(x); else right_rotate(x); } else { if(rightson[z]==y&&rightson[y]==x)left_rotate(y),left_rotate(x); else if(rightson[z]==y&&leftson[y]==x)right_rotate(x),left_rotate(x); else if(leftson[z]==y&&rightson[y]==x)left_rotate(x),right_rotate(x); else right_rotate(y),right_rotate(x); } } root=x; } void BSTinsert(int v,int x)//在二叉搜索樹裏插入 { // cout<<x<<"-------"<<value[x]<<"---------"<<v<<endl; if(value[x]==v)//已經存在了 { splay(x); f=0; return ; } if(value[x]>v) { if(leftson[x]==-1)//插在此處 { leftson[x]=tot; father[tot]=x; leftson[tot]=rightson[tot]=-1; value[tot]=v; } else BSTinsert(v,leftson[x]); } else { if(rightson[x]==-1) { rightson[x]=tot; father[tot]=x; leftson[tot]=rightson[tot]=-1; value[tot]=v; } else BSTinsert(v,rightson[x]); } } int qq(int x)//前驅 { int y=leftson[x]; if(y==-1)return y; while(rightson[y]!=-1)y=rightson[y]; return y; } int hj(int x)//後繼 { int y=rightson[x]; if(y==-1)return y; while(leftson[y]!=-1)y=leftson[y]; return y; } void insertpoint(int v) { tot++; f=1; BSTinsert(v,root); if(!f) { tot--; return ;//有重復的點 } // cout<<value[tot]<<"*****************"<<father[tot]<<endl; splay(tot); int q=qq(tot),h=hj(tot);//找前驅和後繼 int res=3000000; if(q!=-1)res=min(res,abs(value[tot]-value[q])); if(h!=-1)res=min(res,abs(value[tot]-value[h])); ans+=res; } int main() { int n; while(~scanf("%d",&n)) { scanf("%lld",&ans); tot=1;father[tot]=-1; leftson[tot]=rightson[tot]=-1; value[tot]=ans,root=tot; for(int i=2;i<=n;i++) { int a; scanf("%d",&a); insertpoint(a); } printf("%lld\n",ans); } return 0; } /******************** ********************/
HYSBZ - 1588 splay