很模板的一道 Treap,在基本的插入删除操作的前提下,只需支持寻找前驱和后继
在寻找前驱后继时,记得要考虑边界情况(就是没有前驱或后继)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<ctime>
using namespace std;
const long long Maxn=1000000+10,inf=(1ll<<60);
struct node{
long long ls,rs,val,pri,cnt;
#define ls(x) g[x].ls
#define rs(x) g[x].rs
#define v(x) g[x].val
#define p(x) g[x].pri
#define c(x) g[x].cnt
}g[Maxn];
long long n,root,ans;
long long tot,idcnt;
bool cur;
inline void zig(long long &x)
{
long long y=ls(x);
ls(x)=rs(y);
rs(y)=x;
x=y;
}
inline void zag(long long &x)
{
long long y=rs(x);
rs(x)=ls(y);
ls(y)=x;
x=y;
}
void ins(long long &x,const long long k)
{
if(!x)
{
x=++idcnt,p(x)=((rand()<<8)+rand())%Maxn;
v(x)=k,c(x)=1;
return;
}
if(v(x)==k)
{
++c(x);
return;
}
if(v(x)>k)
{
ins(ls(x),k);
if(p(ls(x))<p(x))zig(x);
}
else
{
ins(rs(x),k);
if(p(rs(x))<p(x))zag(x);
}
}
void del(long long &x,const long long k)
{
if(v(x)==k)
{
if(c(x)>1){--c(x);return;}
if(!ls(x) || !rs(x))x=ls(x)|rs(x);
else if(p(ls(x))<p(rs(x)))zig(x),del(x,k);
else zag(x),del(x,k);
return;
}
if(v(x)>k)del(ls(x),k);
else del(rs(x),k);
}
long long find_pre(const long long k)
{
long long x=root,ret=0;
while(x)
{
if(v(x)<=k)ret=v(x),x=rs(x);
else x=ls(x);
}
return ret;
}
long long find_nxt(const long long k)
{
long long x=root,ret=0;
while(x)
{
if(v(x)>k)ret=v(x),x=ls(x);
else x=rs(x);
}
return ret;
}
int main()
{
// freopen("in.txt","r",stdin);
srand(time(NULL));
scanf("%lld",&n);
ins(root,inf);
ins(root,-inf);
for(long long i=1;i<=n;++i)
{
long long opt,v;
scanf("%lld%lld",&opt,&v);
if(!tot)
{
cur=opt,++tot;
ins(root,v);continue;
}
else if(opt==cur){ins(root,v),++tot;continue;}
long long x=find_pre(v),y=find_nxt(v);
ans=(ans+min(abs(x-v),abs(y-v)))%1000000;
if(abs(x-v)<=abs(y-v))del(root,x);
else del(root,y);
--tot;
}
printf("%lld\n",ans);
return 0;
}