题意:每天给你一个数,要求统计最小波动值,强制在线的就是每次从已经出现过的数值中找与当前值间隔最小的加起来
题解:splay维护,同时求解当前值的前驱和后继,找距离小的那个就好了
splay是一种二叉搜索树,可以在log(n)的时间内维护,而且通过左旋和右旋避免二叉搜索树退化成一条链,而且可以利用二叉搜索树性质方便的查找前驱和后继
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#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; } /******************** ********************/