M_sea

洛谷2286 [HNOI2004]宠物收养场
Luogu算法考虑只有宠物或者只有领养者。那么这个题跟营业额统计是一样的。但是现在都有,所以考虑建两颗平衡树。需要...
扫描右侧二维码阅读全文
21
2018/09

洛谷2286 [HNOI2004]宠物收养场

Luogu

算法

考虑只有宠物或者只有领养者。那么这个题跟营业额统计是一样的。

但是现在都有,所以考虑建两颗平衡树。

需要支持的操作:插入、删除、非严格前驱后继。

注意一开始插入INF-INF(查询前驱后继的基本操作)

代码

#include <bits/stdc++.h>
#define re register
#define INF 0x3f3f3f3f
using namespace std;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=(X<<3)+(X<<1)+c-'0',c=getchar();
    return X*w;
}

const int MAXN=80010;

struct fhq_treap {
    int ch[MAXN][2];
    int sz[MAXN],val[MAXN],rnd[MAXN];
    int cnt;
    
    inline void init() { cnt=0; }
    inline void pushup(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; }
    inline int new_node(int x) { sz[++cnt]=1,val[cnt]=x,rnd[cnt]=rand(); return cnt; }
    
    inline void split(int now,int k,int& x,int& y) { //权值分裂
        if (!now) { x=y=0; return; }
        if (val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);
        else y=now,split(ch[now][0],k,x,ch[now][0]);
        pushup(now);
    }
    inline int merge(int A,int B) {
        if (!A||!B) return A+B;
        if (rnd[A]<rnd[B]) { ch[A][1]=merge(ch[A][1],B); pushup(A); return A; }
        else { ch[B][0]=merge(A,ch[B][0]); pushup(B); return B; }
    }
    inline int kth(int now,int k) {
        while (1) {
            if (k<=sz[ch[now][0]]) now=ch[now][0];
            else if (k==sz[ch[now][0]]+1) return now;
            else k-=sz[ch[now][0]]+1,now=ch[now][1];
        }
    }
    inline int getLast(int& now,int k) {
        int x,y; split(now,k,x,y);
        int ans=val[kth(x,sz[x])];
        now=merge(x,y);
        return ans;
    }
    inline int getNext(int& now,int k) {
        int x,y; split(now,k-1,x,y);
        int ans=val[kth(y,1)];
        now=merge(x,y);
        return ans;
    }
    inline void del(int& now,int k) {
        int x,y,z;
        split(now,k,x,z);
        split(x,k-1,x,y);
        y=merge(ch[y][0],ch[y][1]);
        now=merge(merge(x,y),z);
    }
    inline void insert(int& now,int k) {
        int x,y; split(now,k,x,y);
        now=merge(merge(x,new_node(k)),y);
    }
};

fhq_treap T1,T2; //T1是宠物,T2是领养者 
int R1,R2;

int main() {
    T1.init(); T2.init();
    int n=read(),ans=0;
    T1.insert(R1,-INF); T1.insert(R1,INF);
    T2.insert(R2,-INF); T2.insert(R2,INF);
    for (re int i=1;i<=n;i++) {
        int tp=read(),s=read();
        if (tp==0) {
            if (T2.sz[R2]==2) T1.insert(R1,s); //没人领了 
            else {
                int a=T2.getLast(R2,s),b=T2.getNext(R2,s);
                int la=s-a,lb=b-s;
                if (la<=lb) { ans+=la; T2.del(R2,a); }
                else { ans+=lb; T2.del(R2,b); }
            }
        }
        else if (tp==1) {
            if (T1.sz[R1]==2) T2.insert(R2,s);
            else {
                int a=T1.getLast(R1,s),b=T1.getNext(R1,s);
                int la=s-a,lb=b-s;
                if (la<=lb) { ans+=la; T1.del(R1,a); }
                else { ans+=lb; T1.del(R1,b); }
            }
        }
        (ans+=1000000)%=1000000;
    }
    printf("%d\n",ans);
    return 0;
}
最后修改:2019 年 05 月 26 日 03 : 01 PM

发表评论