题目:宠物收养场
思路:
由于同一时间不可能同时有人和狗,所以只需要建立一棵平衡树,赋予一个属性代表人或狗。
然后对于领养操作,查找前驱后继,取差的绝对值最小,删除即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 80000
#define read(x) scanf("%d",&x)
#define inf (int)1e9
#define md 1000000
struct Node{
int fa,sz,val;
int ch[2];
};
int n;
Node a[maxn*10+5];
int rt,cnt,knd;
void push_up(int x) {
a[x].sz=a[a[x].ch[0]].sz+a[a[x].ch[1]].sz;
}
void rotate(int x) {
int fa1=a[x].fa,fa2=a[fa1].fa;
int k=(x==a[fa1].ch[1]);
a[fa2].ch[fa1==a[fa2].ch[1]]=x,a[x].fa=fa2;
a[fa1].ch[k]=a[x].ch[k^1],a[a[x].ch[k^1]].fa=fa1;
a[x].ch[k^1]=fa1,a[fa1].fa=x;
push_up(fa1),push_up(x);
}
void splay(int x,int k){
while(a[x].fa!=k) {
int fa1=a[x].fa,fa2=a[fa1].fa;
if(k!=fa2) {
if((a[fa1].ch[0]==x)^(a[fa2].ch[0]==fa1)) rotate(x);
else rotate(fa1);
}
rotate(x);
}
if(!k) rt=x;
}
void insert(int x) {
int u=rt,fu=0;
while(u) {fu=u,u=a[u].ch[x>a[u].val];}
u=fu;
a[++cnt].val=x;
a[cnt].fa=u;a[cnt].sz++;
a[u].ch[x>a[u].val]=cnt;
splay(cnt,0);
}
void find(int x) {
int u=rt;
while(a[u].ch[x>a[u].val]&&x!=a[u].val) {
u=a[u].ch[x>a[u].val];
}
splay(u,0);
}
int nxt(int x,int k) {
find(x);
int u=rt;
if((a[u].val<x&&!k)||(a[u].val>x&&k)) return u;
u=a[u].ch[k];
while(a[u].ch[k^1]) u=a[u].ch[k^1];
return u;
}
void del(int x) {
int y=nxt(a[x].val,0),z=nxt(a[x].val,1);find(x);
splay(y,0),splay(z,y);
a[z].ch[0]=0;
a[x].fa=-1;
cnt--;
}
int main() {
int ans=0;
read(n);
insert(inf);
insert(-inf);
for(int i=1;i<=n;i++) {
int x,y;
read(x),read(y);
if(cnt==2) insert(y),knd=x;
else if(knd^x) {
find(y);
if(a[rt].val==y) {del(rt);continue;}
int k1=nxt(y,0),k2=nxt(y,1);
int s1=a[k1].val,s2=a[k2].val;
if(abs(y-s1)<=abs(s2-y)) {ans=(ans+abs(y-s1))%md;del(k1);}
else {ans=(ans+abs(s2-y))%md;del(k2);}
} else {insert(y);}
}
printf("%d",ans);
return 0;
}