bzoj 3224(splay/treap)

来源:互联网 发布:工业控制网络结构 编辑:程序博客网 时间:2024/05/02 14:26

传送门
慢的要死的splay,比别人的splay慢了至少30%。。。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN=1e5+2;int ch[2][MAXN],f[MAXN],siz[MAXN],cnt[MAXN],key[MAXN];int sz,root;inline void clear(int x) {    ch[0][x]=ch[1][x]=f[x]=siz[x]=cnt[x]=key[x]=0;}inline bool get(int x) {    return ch[1][f[x]]==x;}inline void update(int x) {    siz[x]=siz[ch[0][x]]+siz[ch[1][x]]+cnt[x];}inline void rotate(int x) {    int old=f[x],oldf=f[old],which=get(x);    ch[which][old]=ch[!which][x],f[ch[which][old]]=old,ch[!which][x]=old;    f[old]=x,f[x]=oldf;    if (oldf) ch[ch[1][oldf]==old][oldf]=x;    update(old),update(x);}inline void splay(int x) {    for (int fa;fa=f[x];rotate(x))        if (f[fa]) rotate(get(x)==get(fa)?fa:x);    root=x;}inline void Insert(int x) {    if (!root) {        ++sz;        ch[0][sz]=ch[1][sz]=f[sz]=0,root=sz,siz[sz]=cnt[sz]=1,key[sz]=x;        return ;    }    int now=root,fa=0;    while (1) {        if (x==key[now]) {            ++cnt[now],update(now),update(fa),splay(now);            break;         }        fa=now;        now=ch[key[now]<x][now];        if (!now) {            ++sz;            ch[0][sz]=ch[1][sz]=0,f[sz]=fa,siz[sz]=cnt[sz]=1;            ch[key[fa]<x][fa]=sz,key[sz]=x;            update(fa);            splay(sz);            break;        }    }}inline int rank(int x) {    int now=root,ans=0;    while (1) {        if (x<key[now]) now=ch[0][now];        else {            ans+=(ch[0][now]?siz[ch[0][now]]:0);            if (x==key[now]) {                splay(now);                return ans+1;            }            ans+=cnt[now];            now=ch[1][now];        }    }}inline int find(int x) {    int now=root;    while (1) {        if (ch[0][now]&&x<=siz[ch[0][now]]) now=ch[0][now];        else {            int temp=(ch[0][now]?siz[ch[0][now]]:0)+cnt[now];            if (x<=temp) return key[now];            x-=temp;now=ch[1][now];        }    }}inline int pre() {    int now=ch[0][root];    while (ch[1][now]) now=ch[1][now];    return now;}inline int nxt() {    int now=ch[1][root];    while (ch[0][now]) now=ch[0][now];    return now;}inline void del(int x) {    int must=rank(x);    if (cnt[root]>1) {--cnt[root];update(root);return ;}    if (!ch[0][root]&&!ch[1][root]) {clear(root);root=0;return ;}    if (!ch[0][root]) {        int oldroot=root;        root=ch[1][root],f[root]=0,clear(oldroot);        return ;    }    else if (!ch[1][root]) {        int oldroot=root;        root=ch[0][root],f[root]=0,clear(oldroot);        return ;    }    int leftbig=pre(),oldroot=root;    splay(leftbig);    ch[1][root]=ch[1][oldroot];    f[ch[1][oldroot]]=root;    clear(oldroot);    update(root);}int main() {//  freopen("bzoj 3224.in","r",stdin);    int n,opt,x;    scanf("%d",&n);    for (register int i=0;i<n;++i) {        scanf("%d%d",&opt,&x);        switch (opt) {            case 1:{Insert(x);break;}            case 2:{del(x);break;}            case 3:{printf("%d\n",rank(x));break;}            case 4:{printf("%d\n",find(x));break;}            case 5:{Insert(x);printf("%d\n",key[pre()]);del(x);break;}            case 6:{Insert(x);printf("%d\n",key[nxt()]);del(x);break;}        }    }    return 0;}

treap还勉强说得过去。

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;struct data{    int l,r,v,size,rnd,w;//左/右儿子,权值,子树大小,优先级,重复计数    data() {l=0,r=0,size=0,w=0;}}node[100004];int n,size,root,ans,opt,x;//x为权值inline int randad(){   static int seed=426;   return seed=int(seed*48271LL%2147483647);}inline void update(int k) {    node[k].size=node[node[k].l].size+node[node[k].r].size+node[k].w;}void rturn(int &k) {    int t=node[k].l;    node[k].l=node[t].r;    node[t].r=k;    node[t].size=node[k].size;    update(k);    k=t;}void lturn(int &k) {    int t=node[k].r;    node[k].r=node[t].l;    node[t].l=k;    node[t].size=node[k].size;    update(k);    k=t;}void insert(int &k,int x) {    if (k==0) {        k=++size;        node[k].size=node[k].w=1,node[k].v=x,node[k].rnd=randad();        return;    }    ++node[k].size;    if (x==node[k].v) ++node[k].w;//当前为位,重复计数一次     else if (x>node[k].v) {//插入右子树         insert(node[k].r,x);        if (node[node[k].r].rnd<node[k].rnd) lturn(k);    }    else {//插入左子树         insert(node[k].l,x);        if (node[node[k].l].rnd<node[k].rnd) rturn(k);    } }void del(int &k,int x) {    if (k==0) return;     if (node[k].v==x) {        if (node[k].w>1) {--node[k].w;--node[k].size;return;}        if (!node[k].l||!node[k].r) k=node[k].l+node[k].r;//直接让儿子代替自己         else if (node[node[k].l].rnd<node[node[k].r].rnd) rturn(k),del(k,x);        else lturn(k),del(k,x);    }    else if (x>node[k].v) --node[k].size,del(node[k].r,x);//处理右子树    else --node[k].size,del(node[k].l,x);//处理左子树 }int rank(int k,int x) {//数x排名第几     if (k==0) return 0;    if (node[k].v==x)        return node[node[k].l].size+1;    else if (x>node[k].v)        return node[node[k].l].size+node[k].w+rank(node[k].r,x);    else return rank(node[k].l,x);}int num(int k,int x) {//排第x的是啥     if (k==0) return 0;    if (x<=node[node[k].l].size) return num(node[k].l,x);    else if (x>node[node[k].l].size+node[k].w) return num(node[k].r,x-node[node[k].l].size-node[k].w);    else return node[k].v;}void pro(int k,int x) {//数x的前驱     if (k==0) return ;    if (node[k].v<x) ans=k,pro(node[k].r,x);     else pro(node[k].l,x);}void sub(int k,int x) {//数x的后继     if (k==0) return ;    if (node[k].v>x) ans=k,sub(node[k].l,x);     else sub(node[k].r,x);}int main() {    scanf("%d",&n);    for (int i=1;i<=n;++i) {        scanf("%d%d",&opt,&x);        switch(opt) {            case 1:insert(root,x);break;            case 2:del(root,x);break;            case 3:printf("%d\n",rank(root,x));break;            case 4:printf("%d\n",num(root,x));break;            case 5:ans=0;pro(root,x);printf("%d\n",node[ans].v);break;            case 6:ans=0;sub(root,x);printf("%d\n",node[ans].v);break;        }    }    return 0;}
原创粉丝点击