题目
思路
建2棵平衡树,一个存宠物,一个存顾客,然后看数量,随时切换就好了。
struct套struct是个好东西
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
long long n,inf=0x7fffffff;
struct Treap{
long long l,r;//左右子编号
long long v,d;//v权值(真),d随机值(旋转用)
long long cnt,size;//cnt重复个数,size子树大小
};
struct f{
Treap a[100010];
long long tot,root=1,rank1,v;
long long New()//新建节点
{
a[++tot].v=v;
a[tot].d=rand();
a[tot].cnt=1;
a[tot].size=1;
return tot;
}
void Up(long long x)
{
a[x].size=a[a[x].l].size+a[a[x].r].size+a[x].cnt;
return;
}
void Build()
{
v=-inf;
root=New();
v=inf;
a[root].r=New();
//避免越界
Up(root);
return;
}
long long GRBV(long long x)//求排名
{
if (x==0) return -2;//未查询到结果
if (v==a[x].v) return a[a[x].l].size+1;//返回排名
if (v<a[x].v) return GRBV(a[x].l);
return GRBV(a[x].r)+a[a[x].l].size+a[x].cnt;//类似二分
}
long long GVBR(long long x)//求值
{
if (x==0) return 0x7fffffff;//未查询到结果
if (a[a[x].l].size>=rank1) return GVBR(a[x].l);//二分
if (a[a[x].l].size+a[x].cnt>=rank1) return a[x].v;//返回结果
rank1-=a[a[x].l].size+a[x].cnt;
return GVBR(a[x].r);//二分
}
void zig(long long &x)//右旋(左节点变父节点)
{
long long y=a[x].l;
a[x].l=a[y].r,a[y].r=x,x=y;
Up(a[x].r),Up(x);
return;
}
void zag(long long &x)//左旋(右节点变父节点)
{
long long y=a[x].r;
a[x].r=a[y].l,a[y].l=x,x=y;
Up(a[x].l),Up(x);
return;
}
void Insert(long long &x)//插入
{
if (x==0)//新建节点
{
x=New();
return;
}
if (v==a[x].v)//已有节点,个数+1
{
a[x].cnt++,Up(x);
return;
}
if (v<a[x].v)//二分
{
Insert(a[x].l);
if (a[x].d<a[a[x].l].d) zig(x);
Up(x);
return;
}
Insert(a[x].r);
if (a[x].d<a[a[x].r].d) zag(x);
Up(x);
return;
}
long long GP()//求前缀
{
long long ans=0x7fffffff,x=root;
while (x)
{
if (v>a[x].v)
{
ans=a[x].v,x=a[x].r;
}
else x=a[x].l;
}
return ans;
}
long long GN()//求后缀
{
long long ans=0x7fffffff,x=root;
while (x)
{
if (v<a[x].v)
{
ans=a[x].v,x=a[x].l;
}
else x=a[x].r;
}
return ans;
}
void Erase(long long &x)//删除
{
if (x==0) return;
if (v==a[x].v)
{
if (a[x].cnt>1)
{
a[x].cnt--,Up(x);
return;//多个,删一个
}
if (a[x].l||a[x].r)//有子节点
{
if (a[x].r==0||a[a[x].l].d>a[a[x].r].d) zig(x),Erase(a[x].r);
else zag(x),Erase(a[x].l);//旋转,然后删除节点(保证平衡)
Up(x);
}
else x=0;
return;
}
if (v<a[x].v)
{
Erase(a[x].l);
}
else
{
Erase(a[x].r);
}//二分
Up(x);
return;
}
} a,b;
int main()
{
srand(114514);
a.Build();
b.Build();
cin>>n;
long long o,x,ljh=0,lyw=0,s=0;
while (n--)
{
cin>>o>>x;
if (o==1)
{
if (ljh!=0)
{
ljh--;
a.v=x+1;
long long xx=a.GP();
a.v-=2;
long long yy=a.GN();
if (abs(x-xx)<=abs(yy-x))
{
s=(s+abs(x-xx))%1000000;
a.v=xx;
a.Erase(a.root);
}
else
{
s=(s+abs(x-yy))%1000000;
a.v=yy;
a.Erase(a.root);
}
}
else
{
lyw++;
b.v=x;
b.Insert(b.root);
}
}
else
{
if (lyw!=0)
{
lyw--;
b.v=x+1;
long long xx=b.GP();
b.v-=2;
long long yy=b.GN();
if (abs(x-xx)<abs(yy-x))
{
s=(s+abs(x-xx))%1000000;
b.v=xx;
b.Erase(b.root);
}
else
{
s=(s+abs(x-yy))%1000000;
b.v=yy;
b.Erase(b.root);
}
}
else
{
ljh++;
a.v=x;
a.Insert(a.root);
}
}
}
cout<<s;
return 0;
}