[BZOJ][HNOI2004]寵物收養所

題目來源:http://www.lydsy.com/JudgeOnline/problem.php?id=1208
這是一份極其“優美”的代碼,本來以爲附帶大常數,結果和hzwer的跑的一樣快。。。雖然代碼本身確實比較差
splay建一棵即可,在樹上標上當前是“寵物樹”還是“領養者樹”。
findval用來找小於等於x的最大值y的位置。比較abs(y-b)和abs(y的後繼-b)的大小,注意判斷x小於樹中的所有值的情況,此時findval會返回0。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define lch ch[x][0]
#define rch ch[x][1]
using namespace std;
const int N=100010,mod=1000000;
int n,ans=0;
bool flag;
int read () {
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9') {
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
struct Splay {
    int ch[N][2],f[N],cnt,root,opt;
    int a[N],s[N];
    void pushup (int x) {
        s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
    }
    int grow (int k,int fa) {
        int x=++cnt;
        a[x]=k,s[x]=1;
        ch[x][0]=ch[x][1]=0,f[x]=fa;
        return x;
    }
    void rotate (int x) {
        int y=f[x],opt;
        if (ch[y][0]==x) opt=0;else opt=1;
        ch[y][opt]=ch[x][!opt];
        if (ch[x][!opt]) f[ch[x][!opt]]=y;
        f[x]=f[y];
        if (root==y) root=x;
        else if (ch[f[y]][0]==y) ch[f[y]][0]=x;
            else ch[f[y]][1]=x;
        ch[x][!opt]=y,f[y]=x;
        pushup(y),pushup(x);
    }
    void splay (int x,int to=0) {
        while (f[x]!=to) {
            if (f[f[x]]==to) rotate(x);
            else if ((ch[f[f[x]]][0]==f[x])
                ==(ch[f[x]][0]==x))
                rotate(f[x]),rotate(x);
                else rotate(x),rotate(x);
        }
    }
    int findval (int k) {
        int x=root,ans=0;flag=0;
        while (x) {
            if (k==a[x]) { flag=1;return x; }
            else if (k<a[x]) x=ch[x][0];
            else ans=x,x=ch[x][1];
        }
        return ans;
    }
    int findkth (int k) {
        int x=root;
        while (x) {
            if (k==s[ch[x][0]]+1)
                return x;
            else if (k<s[ch[x][0]]+1) x=ch[x][0];
            else k-=s[ch[x][0]]+1,x=ch[x][1];
        }
    }
    void insert (int k) {
        if (root==0) root=grow(k,0);
        else {
            int x=root;
            while (x) {
                if (k==a[x]) { break; }
                else {
                    int &y=(k<a[x]?ch[x][0]:ch[x][1]);
                    if (!y) { x=y=grow(k,x);break; }
                    else x=y;
                }
            }
            splay(x);
        }
    }
    void erase (int x) {
        splay(x);
        int p=ch[x][0];
        while (ch[p][1]) p=ch[p][1];
        if (p) {
            splay(p,root);
            ch[p][1]=ch[root][1];
            f[f[ch[root][1]]=p]=0;//這裏之前敲錯了
            pushup(root=p);
        }
        else {
            if (ch[root][1]) f[ch[root][1]]=0,root=ch[root][1];
            else root=cnt=0;
        }
    }
    int next (int x) {
        splay(x);
        int p=ch[x][1];
        while (ch[p][0]) p=ch[p][0];
        if (p) return p;
        return 0;
    }
    Splay () { cnt=root=0; }
}Sp;
int main () {
    int c,x,t,u,v,tmp;
    n=read();
    for (int i=1;i<=n;i++) {
        c=read();x=read();
        if (!Sp.cnt) { Sp.opt=c;Sp.insert(x); }
        else if (c==Sp.opt) Sp.insert(x);
        else {
            t=Sp.findval(x);
            if (t) {
                u=abs(Sp.a[t]-x);
                if (flag) Sp.erase(t);
                if (!flag) {
                    if (tmp=Sp.next(t)) {
                        v=abs(Sp.a[tmp]-x);
                        if (u<=v) { ans=(ans+u)%mod;Sp.erase(t); }
                        else if (u>v) { ans=(ans+v)%mod;Sp.erase(tmp); }
                    }
                    else { ans=(ans+u)%mod;Sp.erase(t); }
                }
            }
            else { tmp=Sp.findkth(1);ans=(ans+abs(Sp.a[tmp]-x))%mod;Sp.erase(tmp); }
        }
    }
    printf("%d\n",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章