【BZOJ3224】【codevs4543】【tyvj1728】普通平衡树,第一次的splay

来源:互联网 发布:java 中间件 面试题 编辑:程序博客网 时间:2024/05/22 12:20

传送门1
传送门2
传送门3
写在前面:woc……woc……大家知道为什么这么久没写题解了吧
思路:不会用指针千万别用!千万别手贱多写函数!千万多调用splay!
感谢http://blog.csdn.net/leolin_/article/details/6436037
http://codevs.cn/wiki/solution/?problem_id=4543
solution16851
注意:数组版splay,个人不喜欢压行,代码写了4k,个人感觉思路还是蛮清晰的,没有特别的技巧,不推荐作为模板使用
代码:

#include"bits/stdc++.h"using namespace std;int n,root,tot;struct os{    int left,right,father,sz,occ,data;}a[300000];void ct(int root){    a[root].sz=a[root].occ+a[a[root].left].sz+a[a[root].right].sz;}void made(int x){    a[++tot].data=x;    a[tot].sz=a[tot].occ=1;}void rotate(int x,bool flag){    int y=a[x].father;    if (flag)    {        a[y].left=a[x].right;        if (a[x].right) a[a[x].right].father=y;        a[x].father=a[y].father;        if (a[y].father)        {            if (a[a[y].father].left==y)            a[a[y].father].left=x;            else a[a[y].father].right=x;        }        a[x].right=y;        a[y].father=x;    }    else    {        a[y].right=a[x].left;        if (a[x].left) a[a[x].left].father=y;        a[x].father=a[y].father;        if (a[y].father)        {            if (a[a[y].father].left==y)            a[a[y].father].left=x;            else a[a[y].father].right=x;        }        a[x].left=y;        a[y].father=x;      }    ct(y);    ct(x);}void splay(int x,int goal){    int y;    while (a[x].father!=goal)    {        y=a[x].father;        if (a[y].father==goal)        {            if (a[y].left==x) rotate(x,1);            else rotate(x,0);        }        else if (a[a[y].father].left==y)        {            if (a[y].left==x) rotate(y,1);            else rotate(x,0);            rotate(x,1);        }        else        {            if (a[y].right==x) rotate(y,0);            else rotate(x,1);            rotate(x,0);        }    }    if (!goal) root=x;}void insert(int now,int x){    if (!root) {made(x);root=tot;return;}    int flag=0;    while (!flag)    {        a[now].sz++;        if (a[now].data==x) a[now].occ++,flag=2;        else if (a[now].data>x)        {            if (!a[now].left) made(x),a[now].left=tot,a[tot].father=now,flag=1;            else now=a[now].left;        }        else        {            if (!a[now].right) made(x),a[now].right=tot,a[tot].father=now,flag=1;            else now=a[now].right;        }    }    splay((flag==1)?tot:now,0);}int find(int now,int x){    while (now)    {        if (a[now].data==x) {splay(now,0);return now;}        else if (a[now].data>x) now=a[now].left;        else now=a[now].right;    }    return 0;}int find_max(int now){    int pa=a[now].father;    if (!now) return 0;    while (a[now].right) now=a[now].right;    splay(now,pa);    return now;}int find_min(int now){    int pa=a[now].father;    if (!now) return 0;    while (a[now].left) now=a[now].left;    splay(now,pa);    return now;}int find_next_min(int x){    int ans=0,now=root;    while (now)    {        if (a[now].data>=x) now=a[now].left;        else ans=(a[now].data>a[ans].data||!ans)?now:ans,now=a[now].right;    }    splay(ans,0);    return ans;}int find_next_max(int x){    int ans=0,now=root;    while (now)    {        if (a[now].data<=x) now=a[now].right;        else ans=(a[now].data<a[ans].data||!ans)?now:ans,now=a[now].left;    }    splay(ans,0);    return ans;}bool del(int x){    int now=find(root,x);    if (!now) return 0;    splay(now,0);    if (a[now].occ>1)    {        --a[now].occ;        --a[now].sz;        return 1;    }    if (!a[now].left&&!a[now].right) root=0;    else if (!a[now].left)    {        root=a[now].right;        a[a[now].right].father=0;    }    else if (!a[now].right)    {        root=a[now].left;        a[a[now].left].father=0;    }    else    {        splay(find_max(a[now].left),root);        a[a[now].left].right=a[now].right;        a[a[now].right].father=a[now].left;        a[a[now].left].father=0;        root=a[now].left;        ct(a[now].left);    }    ct(now);    return 1;}int Kth(int k){    int now=root;    int p;    while (now)    {        p=a[a[now].left].sz;        if (k>p&&k<=p+a[now].occ) break;        if (k<=p) now=a[now].left;        else k-=(p+a[now].occ),now=a[now].right;    }    splay(now,0);    return now;}int find_rank(int x){    int ans=0,now=root;    while (1)    {        if (x<a[now].data) now=a[now].left;        else        {            if (x==a[now].data)            {                ans+=a[a[now].left].sz+1;                break;            }            else ans+=a[a[now].left].sz+a[now].occ,now=a[now].right;        }    }    splay(now,0);    return ans;}main(){    scanf("%d",&n);    for (int i=1;i<=n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        if (x==1) insert(root,y);        else if (x==2) del(y);        else if (x==3) printf("%d\n",find_rank(y));        else if (x==4) printf("%d\n",a[Kth(y)].data);        else if (x==5) printf("%d\n",a[find_next_min(y)].data);        else if (x==6) printf("%d\n",a[find_next_max(y)].data);    }}

UPD
2017.3.23
学习后缀平衡树时搞了一发treap

#include<cstdio>#include<iostream>#include<cstdlib>#define ls(x) tr[x].ch[0]#define rs(x) tr[x].ch[1]#define son(x,y) tr[x].ch[y]#define M 100005using namespace std;int n,m,seed,root,cnt;int in(){    int t=0;char ch=getchar();bool f=0;    while (ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();    while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();    return f?-t:t;} int ran(){    seed=seed^rand();    seed^=(seed<<7);    seed^=(seed>>3);    return seed;}struct Treap{    int key,fix,siz,occ,fa,ch[2];    void build(int Fa,int val)    {        key=val;        fa=Fa;        fix=ran();        siz=occ=1;        ch[0]=ch[1]=0;    }}tr[M];void count(int rt){    tr[rt].siz=tr[ls(rt)].siz+tr[rs(rt)].siz+tr[rt].occ;}void rotate(int x,bool f){    int y=tr[x].fa;    son(y,!f)=son(x,f);    if (son(x,f)) tr[son(x,f)].fa=y;    tr[x].fa=tr[y].fa;    if (tr[y].fa)        if (ls(tr[y].fa)==y) ls(tr[y].fa)=x;        else rs(tr[y].fa)=x;    son(x,f)=y;    tr[y].fa=x;    count(y);    count(x);}void insert(int rt,int val){    if (tr[rt].key==val) ++tr[rt].occ,++tr[rt].siz;    else if (tr[rt].key>val)    {        if (ls(rt))            insert(ls(rt),val);        else            tr[ls(rt)=++cnt].build(rt,val);        if (tr[ls(rt)].fix<tr[rt].fix)        {            if (!tr[rt].fa) root=ls(rt);            rotate(ls(rt),1);        }    }    else    {        if (rs(rt))            insert(rs(rt),val);        else            tr[rs(rt)=++cnt].build(rt,val);        if (tr[rs(rt)].fix<tr[rt].fix)        {            if (!tr[rt].fa) root=rs(rt);            rotate(rs(rt),0);        }    }    count(rt);}void del(int rt,int val){    if (tr[rt].key==val)    {        if (tr[rt].occ>1) --tr[rt].occ,--tr[rt].siz;        else if (!ls(rt)&&!rs(rt))            if (!tr[rt].fa) root=0;            else            {                if (rt==ls(tr[rt].fa)) ls(tr[rt].fa)=0;                else rs(tr[rt].fa)=0;            }        else if (!ls(rt))            if (!tr[rt].fa) root=rs(rt),tr[rs(rt)].fa=0;            else            {                tr[rs(rt)].fa=tr[rt].fa;                if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=rs(rt);                else rs(tr[rt].fa)=rs(rt);            }        else if (!rs(rt))            if (!tr[rt].fa) root=ls(rt),tr[ls(rt)].fa=0;            else            {                tr[ls(rt)].fa=tr[rt].fa;                if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=ls(rt);                else rs(tr[rt].fa)=ls(rt);            }        else        {            bool f=(tr[ls(rt)].fix<tr[rs(rt)].fix);            int y=son(rt,!f);            if (!tr[rt].fa) root=y;            rotate(y,f);            del(rt,val);            count(y);        }    }    else    {        if (tr[rt].key<val) del(rs(rt),val);        else del(ls(rt),val);        count(rt);     }}int Rank(int val){    int x=root,ans=0;    for (;;)        if (tr[x].key==val) return ans+tr[ls(x)].siz+1;        else if (tr[x].key<val) ans+=tr[ls(x)].siz+tr[x].occ,x=rs(x);        else x=ls(x);}int Kth(int k){    int x=root;    for (;;)        if (tr[ls(x)].siz<k&&k<=tr[ls(x)].siz+tr[x].occ) return tr[x].key;        else if (tr[ls(x)].siz>=k) x=ls(x);        else k-=tr[ls(x)].siz+tr[x].occ,x=rs(x);}int Pre(int val){    int x=root,ans=-1<<30;    for (;x;)        if (tr[x].key<val) ans=max(ans,tr[x].key),x=rs(x);        else x=ls(x);    return ans;}int Sub(int val){    int x=root,ans=1<<30;    for (;x;)        if (tr[x].key>val) ans=min(ans,tr[x].key),x=ls(x);        else x=rs(x);    return ans;}main(){    srand(20170322);    int opt,x;    for (n=in();n;--n)    {        opt=in();x=in();        if (opt==1)        {            if (!root) tr[root=++cnt].build(0,x);            else insert(root,x);        }        else if (opt==2) del(root,x);        else if (opt==3) printf("%d\n",Rank(x));        else if (opt==4) printf("%d\n",Kth(x));        else if (opt==5) printf("%d\n",Pre(x));        else if (opt==6) printf("%d\n",Sub(x));    }}
0 0
原创粉丝点击