题解 P2286 【[HNOI2004]宠物收养场】

这是题目链接

大家好,这个题我调了很久过了,所以想写题解
我用的平衡树是AVL树,平衡树界的老爷爷
这个树并不会很慢,主要是我初学,常数巨大
而且题目的 $ n = 80000$,可以接受

\(solution\):

开两颗平衡树,维护宠物和人,过多就插入自己的平衡树,过少就在对立平衡树中删除与 \(x\) 相差最小的。

也就是确定前驱后继

代码很长,但是操作是相同的,一半都是在复制粘贴

希望注意传参引用,少写一个调了很长时间

\(code:\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 80000+50;
const int mod = 1000000;
int ans;
inline void read(int &k) {
    k=0;char ch=getchar();
    while(ch>'9'||ch<'0') ch=getchar();
    while(ch<='9'&&ch>='0') k=k*10+ch-'0',ch=getchar();
}
namespace pet{
    int root,cnt;
    struct node{
        int l,r,val,height,size;
    }avl[N];
    inline void newnode(int &now,int val) {
        avl[now=++cnt].val=val,avl[now].size=1;
    }
    int factor(int now) {
        return avl[avl[now].l].height-avl[avl[now].r].height;
    }
    void update(int now) {
        avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
        avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
    }
    void zag(int &now) {
        int r=avl[now].r;
        avl[now].r=avl[r].l;
        avl[r].l=now;
        now=r;
        update(avl[now].l),update(now);
    }
    void zig(int &now) {
        int l=avl[now].l;
        avl[now].l=avl[l].r;
        avl[l].r=now;
        now=l;
        update(avl[now].r),update(now);
    }
    void check(int &now) {
        int bf=factor(now);
        if(bf>1) {
            int lf=factor(now);
            if(lf>0) zig(now);
            else zag(avl[now].l),zig(now);
        }else if(bf<-1) {
            int rf=factor(now);
            if(rf<0) zag(now);
            else zig(avl[now].r),zag(now);
        }else if(now) update(now);
    }
    void ins(int &now,int val) {
        if(!now) newnode(now,val);
        else if(avl[now].val>val) ins(avl[now].l,val);
        else ins(avl[now].r,val);
        check(now);
    }
    int find(int &now,int fa) {
        int tmp;
        if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
        else tmp=find(avl[now].l,now),check(now);
        return tmp;
    }
    void del(int &now,int val) {
        if(avl[now].val==val) {
            int l=avl[now].l,r=avl[now].r;
            if(!l||!r) now=l+r;
            else {
                now=find(r,r);
                if(now!=r) avl[now].r=r;
                avl[now].l=l;
            }
        }else if(avl[now].val>val) del(avl[now].l,val);
        else del(avl[now].r,val);
        check(now);
    }
    int getrank(int val) {
        int now=root,rank=1;
        while(now) {
            if(val<=avl[now].val) now=avl[now].l;
            else rank+=avl[avl[now].l].size+1,now=avl[now].r;
        }
        return rank;
    }
    int getnum(int rank) {
        int now=root;
        while(now) {
            if(rank==avl[avl[now].l].size+1) break;
            else if(rank<=avl[avl[now].l].size) now=avl[now].l;
            else rank-=avl[avl[now].l].size+1,now=avl[now].r;
        }
        return avl[now].val;
    }
    int search(int now,int val) {
        if(!now) return false;
        if(val==avl[now].val) return true;
        else if(val<avl[now].val) return search(avl[now].l,val);
        else return search(avl[now].r,val);
        return false;
    }
}
namespace human{
    int root,cnt;
    struct node{
        int l,r,val,height,size;
    }avl[N];
    inline void newnode(int &now,int val) {
        avl[now=++cnt].val=val,avl[now].size=1;
    }
    int factor(int now) {
        return avl[avl[now].l].height-avl[avl[now].r].height;
    }
    void update(int now) {
        avl[now].size=avl[avl[now].l].size+avl[avl[now].r].size+1;
        avl[now].height=max(avl[avl[now].l].height,avl[avl[now].r].height)+1;
    }
    void zag(int &now) {
        int r=avl[now].r;
        avl[now].r=avl[r].l;
        avl[r].l=now;
        now=r;
        update(avl[now].l),update(now);
    }
    void zig(int &now) {
        int l=avl[now].l;
        avl[now].l=avl[l].r;
        avl[l].r=now;
        now=l;
        update(avl[now].r),update(now);
    }
    void check(int &now) {
        int bf=factor(now);
        if(bf>1) {
            int lf=factor(now);
            if(lf>0) zig(now);
            else zag(avl[now].l),zig(now);
        }else if(bf<-1) {
            int rf=factor(now);
            if(rf<0) zag(now);
            else zig(avl[now].r),zag(now);
        }else if(now) update(now);
    }
    void ins(int &now,int val) {
        if(!now) newnode(now,val);
        else if(avl[now].val>val) ins(avl[now].l,val);
        else ins(avl[now].r,val);
        check(now);
    }
    int find(int &now,int fa) {
        int tmp;
        if(!avl[now].l) tmp=now,avl[fa].l=avl[now].r;
        else tmp=find(avl[now].l,now),check(now);
        return tmp;
    }
    void del(int &now,int val) {
        if(avl[now].val==val) {
            int l=avl[now].l,r=avl[now].r;
            if(!l||!r) now=l+r;
            else {
                now=find(r,r);
                if(now!=r) avl[now].r=r;
                avl[now].l=l;
            }
        }else if(avl[now].val>val) del(avl[now].l,val);
        else del(avl[now].r,val);
        check(now);
    }
    int getrank(int val) {
        int now=root,rank=1;
        while(now) {
            if(val<=avl[now].val) now=avl[now].l;
            else rank+=avl[avl[now].l].size+1,now=avl[now].r;
        }
        return rank;
    }
    int getnum(int rank) {
        int now=root;
        while(now) {
            if(rank==avl[avl[now].l].size+1) break;
            else if(rank<=avl[avl[now].l].size) now=avl[now].l;
            else rank-=avl[avl[now].l].size+1,now=avl[now].r;
        }
        return avl[now].val;
    }
    int search(int now,int val) {
        if(!now) return false;
        if(val==avl[now].val) return true;
        else if(val<avl[now].val) return search(avl[now].l,val);
        else return search(avl[now].r,val);
        return false;
    }
}
signed main() {
    int n; cin>> n;
    while(n--) {
        int opt, x;
//      scanf("%lld%lld",&opt, &x);
        read(opt),read(x);
        if(!opt) {
            if(human::avl[human::root].size) {
                if(human::search(human::root,x)) human::del(human::root,x);
                else {
                    int pre=human::getnum(human::getrank(x)-1);
                    int nxt=human::getnum(human::getrank(x+1));
                    if(pre==0) { ans+=nxt-x,ans%=mod,human::del(human::root,nxt);continue;}
                    if(nxt==0) { ans+=x-pre,ans%=mod,human::del(human::root,pre);continue;}                 
                    if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,human::del(human::root,pre);
                    else ans+=nxt-x,ans%=mod,human::del(human::root,nxt);
                }
            }else pet::ins(pet::root,x);
        }else {
            if(pet::avl[pet::root].size) {
                if(pet::search(pet::root,x)) pet::del(pet::root,x);
                else {
                    int pre=pet::getnum(pet::getrank(x)-1);
                    int nxt=pet::getnum(pet::getrank(x+1));
                    if(pre==0) { ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);continue;}
                    if(nxt==0) { ans+=x-pre,ans%=mod,pet::del(pet::root,pre);continue;}
                    if(x-pre<=nxt-x) ans+=x-pre,ans%=mod,pet::del(pet::root,pre);
                    else ans+=nxt-x,ans%=mod,pet::del(pet::root,nxt);
                }
            }else human::ins(human::root,x);            
        }
    }
    cout<<ans;  
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/skkyk/p/12079930.html