P2286 [HNOI2004]宠物收养场

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; }
原文地址:https://www.cnblogs.com/kafuuchino/p/9727167.html