Bzoj1588--Hnoi2002营业额统计

平衡树练习

每次插入一个数判断是否重复,重复则返回0,否则选出与它差最小的数返回差的绝对值

最小差必定是左子树中最大点或右子树中最小点或其祖先,找找就可以了

代码:

#include<bits/stdc++.h>
#define MAXN 300005
#define MAXM 3005
#define INF 10000000000000LL
#define MOD 998244353
#define LL long long
using namespace std;

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

inline LL _abs(LL a) {return a>0?a:-a;}

int n;

struct node{
    int son[2],par;LL v,r;
}x[MAXN];
struct Treap{
    int L,R,root,cnt;
    void init() {
        L=0;R=1;root=MAXN-5;cnt=0;
        x[MAXN-5].r=INF;x[MAXN-5].v=INF;
    }
    
    inline void rotate(int num,int p) {
        int pa=x[num].par;
        x[x[pa].par].son[x[x[pa].par].son[L]==pa?L:R]=num;
        x[pa].son[p^1]=x[num].son[p];if(x[num].son[p]) {x[x[num].son[p]].par=pa;}
        x[num].son[p]=pa;x[num].par=x[pa].par;x[pa].par=num;
    }
    
    int Insert(int v) {
        x[++cnt].v=v;x[cnt].r=rand()%MOD;
        int now=root,pre;LL le,ri;
        while(true) {
            if(v==x[now].v) {cnt--;return 0;}
            pre=v<x[now].v?L:R;
            if(!x[now].son[pre]) {x[now].son[pre]=cnt;x[cnt].par=now;break;}
            now=x[now].son[pre];
        }
        now=cnt;
        while(true) {
            if(x[x[now].par].son[L]==now) pre=R;else pre=L;
            if(x[now].r>x[x[now].par].r) rotate(now,pre);
            else break;
        }
        le=x[now].son[L];ri=x[now].son[R];
        while(x[le].son[R]) le=x[le].son[R];
        while(x[ri].son[L]) ri=x[ri].son[L];
        le=le?x[now].v-x[le].v:INF;ri=ri?x[ri].v-x[now].v:INF;
        now=x[now].par;
        if(le==ri&&le==INF&&now==root) return x[cnt].v;
        le=le<ri?le:ri;
        while(now) {
            le=le<_abs(x[now].v-x[cnt].v)?le:_abs(x[now].v-x[cnt].v);
            now=x[now].par;
        }
        return le;
    }
};

int main() {
    srand(2333333);
    n=read();LL ret=0;
    Treap p;p.init();
    for(int k,i=1;i<=n;i++) {
        k=read();
        ret+=p.Insert(k);
    }
    printf("%lld\n",ret);
    return 0;
}

 

posted @ 2016-09-28 12:13  ihopenot  阅读(175)  评论(0编辑  收藏  举报