[BZOJ 1208] 宠物收养所
Link:
Solution:
求前驱后继,很明显的平衡树操作
其实$set$完全可以做,主要是为了复习下$Treap$结果调了好久……
注意:在写平衡树删除时一定要记得考虑删除数不存在的情况
特别是$Treap$,如果访问到空要直接返回否则死循环……
Code:
#include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; typedef double db; const int MAXN=1e5+10,MOD=1e6,INF=1<<30; namespace Treap { int tot,rt; int sz[MAXN],pri[MAXN],val[MAXN],s[MAXN][2]; void Pushup(int x) {sz[x]=sz[s[x][0]]+sz[s[x][1]]+1;} void Rotate(int &x,int f) {//注意这里的旋转 int tmp=s[x][f]; s[x][f]=s[tmp][f^1];s[tmp][f^1]=x; Pushup(x);Pushup(x=tmp); } void Insert(int &x,int k) { if(!x) { x=++tot; pri[x]=rand();val[x]=k; sz[x]=1;return; } int nxt=k>val[x];Insert(s[x][nxt],k); if(pri[x]>pri[s[x][nxt]]) Rotate(x,nxt); Pushup(x); } int Pre(int &x,int k) { if(!x) return -INF; if(k==val[x]) return val[x]; if(k>val[x]) return max(val[x],Pre(s[x][1],k)); else return Pre(s[x][0],k); } int Nxt(int &x,int k) { if(!x) return INF; if(k==val[x]) return val[x]; if(k<val[x]) return min(val[x],Nxt(s[x][0],k)); else return Nxt(s[x][1],k); } void Del(int &x,int k) { if(!x) return;//防止k不存在! if(val[x]==k) { if(s[x][0]*s[x][1]==0) {x=s[x][0]+s[x][1];return;} int nxt=pri[s[x][0]]<pri[s[x][1]]; Rotate(x,nxt^1);Del(s[x][nxt],k); } else Del(s[x][k>val[x]],k); Pushup(x); } } using namespace Treap; int n,x,y,cur,cnt,res; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); if(!cnt||cur==x) cnt++,cur=x,Insert(rt,y); else { int pre=Pre(rt,y),nxt=Nxt(rt,y),tmp; if(nxt-y<y-pre) tmp=nxt-y,Del(rt,nxt); else tmp=y-pre,Del(rt,pre); cnt--;(res+=tmp)%=MOD; } } printf("%d",res); return 0; }