P2286 [HNOI2004]宠物收养场
splay
我们只需要一棵splay
如果有宠物剩下,那么此时就是宠物树。领走的时候查找并删去树内元素,反之亦然。
#include<iostream> #include<cstdio> #include<cstring> #include<cctype> #include<cmath> #define re register using namespace std; template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;} template <typename T> inline T max(T &a,T &b) {return a>b ?a:b;} template <typename T> inline void read(T &x){ char c=getchar(); x=0; bool f=1; while(!isdigit(c)) f= !f||c=='-' ? 0:1,c=getchar(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar(); x= f ? x:-x; } template <typename T> inline void output(T x){ if(!x) {putchar(48); return ;} if(x<0) putchar('-'),x=-x; int wt[50],l=0; while(x) wt[++l]=x%10,x/=10; while(l) putchar(wt[l--]+48); } const int mod=1e6; struct data{int fa,ch[2],v;}a[200002]; int n,u,rt; inline void rte(int x,int &k){ int y=a[x].fa,z=a[y].fa; int l=(a[y].ch[1]==x),r=l^1; if(y==k) k=x; else a[z].ch[a[z].ch[1]==y]=x; a[x].fa=z,a[a[x].ch[r]].fa=y,a[y].fa=x; a[y].ch[l]=a[x].ch[r],a[x].ch[r]=y; } inline void splay(int x,int &k){ for(;x!=k;rte(x,k)){ int y=a[x].fa,z=a[y].fa; if(y!=k){ if((a[y].ch[0]==x)^(a[z].ch[0]==y)) rte(x,k); else rte(y,k); } } }
//-----模板------ inline void ins(int x){ int p=rt,_fa=0; while(p&&a[p].v!=x) _fa=p,p=a[p].ch[a[p].v<x]; if(!p){ p=++u,a[p].fa=_fa,a[p].v=x; if(_fa) a[_fa].ch[a[_fa].v<x]=p; }splay(p,rt);//把新插的点旋到根上,跑得飞快 } inline void find(int x){ //找到元素x在树中的位置并旋到根上 int p=rt; if(!p) return ; while(a[p].ch[a[p].v<x]&&a[p].v!=x) p=a[p].ch[a[p].v<x]; splay(p,rt); } inline int Nxt(int x,int k){ //不严格前驱/后继(可以等于) find(x); int p=rt; if(a[p].v>=x&&k) return p; if(a[p].v<=x&&!k) return p; p=a[p].ch[k]; while(a[p].ch[k^1]) p=a[p].ch[k^1]; return p; } inline int Nxt_une(int x,int k){//严格前驱/后继 find(x); int p=rt; if(a[p].v>x&&k) return p; if(a[p].v<x&&!k) return p; p=a[p].ch[k]; while(a[p].ch[k^1]) p=a[p].ch[k^1]; return p; } inline void remov(int x){ //删除 int p1=Nxt_une(x,0); int p2=Nxt_une(x,1); //找出严格前驱/后继,并旋到根上 splay(p1,rt); splay(p2,a[p1].ch[1]); a[p2].ch[0]=0; } int main(){ read(n); int q1,q2,cnt=0; long long ans=0; ins(-2e8); ins(2e8); for(re int i=1;i<=n;++i){ read(q1),read(q2); if(cnt==0) ins(q2); //空树直接加 else if(cnt>0){ //两种情况 if(q1) ins(q2); else{ int p1=a[Nxt(q2,0)].v; int p2=a[Nxt(q2,1)].v; if(abs(q2-p1)<=abs(p2-q2)) remov(p1),ans+=abs(q2-p1); else remov(p2),ans+=abs(p2-q2); } }else{ if(!q1) ins(q2); else{ int p1=a[Nxt(q2,0)].v; int p2=a[Nxt(q2,1)].v; if(abs(q2-p1)<=abs(p2-q2)) remov(p1),ans+=abs(q2-p1); else remov(p2),ans+=abs(p2-q2); } } cnt+= q1 ? 1:-1; ans%=mod; }printf("%lld",ans); return 0; }