HYSBZ - 1588 splay
Posted walfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HYSBZ - 1588 splay相关的知识,希望对你有一定的参考价值。
题意:每天给你一个数,要求统计最小波动值,强制在线的就是每次从已经出现过的数值中找与当前值间隔最小的加起来
题解: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> #define C 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的主要内容,如果未能解决你的问题,请参考以下文章