Splay到吐血

来源:互联网 发布:淘宝宝贝图片素材 编辑:程序博客网 时间:2024/04/28 11:01

Splay,一种恶心的数据结构。
所有操作基于Splay操作,常数不是一般的大……
使Splay变得复杂起来的,并没有其它,只有代码长度。
所以为了压行大家也都是拼了。
代码是跟着我也不知道是哪位神犇学的(非递归)
思想很简单,转啊转啊转就是了。
(到哪里都有讲解)
上例题:bzoj3224

#include<algorithm>#include<cstdio>using namespace std;int n,rt,sz,op,xx;const int N=0x3fffffff;struct Splay{int ch[2],v,f,sz,cnt;} tr[200005];template <class T> void read(T &x) {    x=0;int f=1;char ch=getchar();    for(;ch<'0'||ch>'9';) {if(ch=='-') f=-1;ch=getchar();}    for(;ch>='0'&&ch<='9';) x=x*10+ch-'0',ch=getchar();x*=f;}inline int Up(int x) {tr[x].sz=tr[tr[x].ch[1]].sz+tr[tr[x].ch[0]].sz+tr[x].cnt;}inline void rot(int x) {    int y=tr[x].f,z=tr[y].f;bool f=(tr[y].ch[1]==x);    tr[y].ch[f]=tr[x].ch[!f];    if(tr[y].ch[f]) tr[tr[y].ch[f]].f=y;    tr[x].ch[!f]=y,tr[y].f=x,tr[x].f=z;    if(z) tr[z].ch[tr[z].ch[1]==y]=x;    Up(y);}inline void splay(int x,int tp) {    for(int y,z;(y=tr[x].f)!=tp;rot(x)) {        if((z=tr[y].f)==tp) continue;        if((tr[z].ch[0]==y)==(tr[y].ch[0]==x)) rot(y);        else rot(x);    }    if(!tp) rt=x;Up(x);}inline void ins(int x,int v) {    int y=0;    for(;x&&tr[x].v!=v;) y=x,x=tr[x].ch[v>tr[x].v];    if(x) ++tr[x].cnt;    else {        x=++sz,tr[x].cnt=tr[x].sz=1,tr[x].f=y,tr[x].v=v;        if(y) tr[y].ch[v>tr[y].v]=x;    }    splay(x,0);}inline void find(int v) {    int x=rt;    for(;tr[x].ch[v>tr[x].v]&&tr[x].v!=v;) x=tr[x].ch[v>tr[x].v];    splay(x,0);}inline int nxt(int v,bool f) {    find(v);    if((tr[rt].v>v&&f)||(tr[rt].v<v&&!f)) return rt;    int p=tr[rt].ch[f];    for(;tr[p].ch[!f];) p=tr[p].ch[!f];    return p;}inline void del(int x) {    int p=nxt(x,0),s=nxt(x,1);    splay(p,0),splay(s,p),p=tr[s].ch[0];    if(tr[p].cnt>1) tr[p].cnt--,splay(p,0);    else tr[s].ch[0]=0;}inline int kth(int x) {    int y=rt,p;    if(x>tr[rt].sz) return 0;    for(;;) {        p=tr[y].ch[0];        if(tr[p].sz+tr[y].cnt<x) x=x-tr[p].sz-tr[y].cnt,y=tr[y].ch[1];        else if(tr[p].sz>=x) y=p; else return tr[y].v;    }}int main() {    for(ins(rt,0x3fffffff),ins(rt,-0x3fffffff),read(n);n--;) {        read(op),read(xx);        if(op==1) ins(rt,xx);        else if(op==2) del(xx);        else if(op==3) find(xx),printf("%d\n",tr[tr[rt].ch[0]].sz);        else if(op==4) printf("%d\n",kth(xx+1));        else printf("%d\n",tr[nxt(xx,op==6)].v);    }}

再上一道例题:poj2892

#include<cstdio>#define N 50005int n,m,rt,sz,tot,op[N],ds[N];struct Node{int v,f,ch[2];} t[N];inline void in(int &x) {    x=0;static char c=' ',f=1;    for(;c<'0'||c>'9';) {if(c=='-') f=-1;c=getchar();}    for(;c>='0'&&c<='9';) x=x*10+c-'0',c=getchar();x*=f;}inline void rot(int x) {    int y=t[x].f,z=t[y].f,f=(t[y].ch[1]==x);    t[y].ch[f]=t[x].ch[!f];    if(t[y].ch[f]) t[t[y].ch[f]].f=y;    t[x].ch[!f]=y,t[y].f=x,t[x].f=z;    if(z) t[z].ch[t[z].ch[1]==y]=x;}inline void Splay(int x,int tp) {    for(int y,z;(y=t[x].f)!=tp;rot(x)) {        if((z=t[y].f)==tp) continue;        if((t[z].ch[0]==y)==(t[y].ch[0]==x)) rot(y);        else rot(x);    }    if(!tp) rt=x;}inline void Ins(int x,int v) {    int y=0;    for(;x&&t[x].v!=v;) y=x,x=t[x].ch[v>t[x].v];    x=++sz,t[x].v=v,t[x].f=y;    if(y) t[y].ch[v>t[y].v]=x;    Splay(x,0);}inline void Find(int v) {    int x=rt;if(!x) return;    for(;t[x].ch[v>t[x].v]&&t[x].v!=v;) x=t[x].ch[v>t[x].v];    Splay(x,0);}inline int Nxt(int v,bool f) {    Find(v);    if((t[rt].v>v&&f)||(t[rt].v<v&&!f)) return rt;    int p=t[rt].ch[f];    for(;t[p].ch[!f];) p=t[p].ch[!f];    return p;}inline void Del(int v) {    int p=Nxt(v,0),s=Nxt(v,1);Splay(p,0),Splay(s,p);    p=t[s].ch[0],t[s].ch[0]=0;}int main() {    char s[3];int x;    for(in(n),Ins(rt,0),Ins(rt,n+1),in(m);m--;) {        scanf("%s",s);        if(s[0]=='D') in(op[++tot]),ds[op[tot]]=1,Ins(rt,op[tot]);        else if(s[0]=='Q') {            in(x);if(ds[x]) puts("0");            else printf("%d\n",t[Nxt(x,1)].v-t[Nxt(x,0)].v-1);        } else ds[op[tot]]=0,Del(op[tot--]);    }    return 0;}

区间操作的的话把区间转到一颗子树(一般是根节点的左儿子的右子树),然后如线段树一般打标记就是了。
上一道相对来说比较好打的例题:poj3580

#include<cstdio>#define N 200005#define min(a,b) (a)<(b)?(a):(b)int sz,rt,tmp,a[N];inline void swap(int &a,int &b) {tmp=a;a=b;b=tmp;}struct Splay {    int f,v,sz,mn,dv,rev,ch[2];    inline void mt() {swap(ch[0],ch[1]);}} t[N];inline void in(int &x) {    x=0;static int f=1;static char c=' ';    for(;c<'0'||c>'9';) {if(c=='-') f=-1;c=getchar();}    for(;c>='0'&&c<='9';) x=x*10+c-'0',c=getchar();x*=f;}inline void pd(int x) {    if(t[x].rev) {        t[x].mt();        if(t[x].ch[0]) t[t[x].ch[0]].rev^=1;        if(t[x].ch[1]) t[t[x].ch[1]].rev^=1;        t[x].rev=0;    }    if(t[x].dv!=0) {        t[x].v+=t[x].dv;        if(t[x].ch[0]) t[t[x].ch[0]].dv+=t[x].dv;        if(t[x].ch[1]) t[t[x].ch[1]].dv+=t[x].dv;        t[x].dv=0;    }}inline void Up(int x) {    t[x].sz=t[t[x].ch[0]].sz+t[t[x].ch[1]].sz+1;    tmp=min(t[t[x].ch[1]].mn+t[t[x].ch[1]].dv,t[x].v+t[x].dv);    t[x].mn=min(t[t[x].ch[0]].mn+t[t[x].ch[0]].dv,tmp);}inline void rot(int x) {    int y=t[x].f,z=t[y].f,f=(t[y].ch[1]==x);    pd(y),pd(x),t[y].ch[f]=t[x].ch[!f];    if(t[y].ch[f]) t[t[y].ch[f]].f=y;    t[x].ch[!f]=y,t[y].f=x,t[x].f=z;    if(z) t[z].ch[t[z].ch[1]==y]=x;Up(y);}inline void Splay(int x,int tp,int &Root=rt) {    for(int y,z;(y=t[x].f)!=tp;rot(x)) {        pd(x);        if((z=t[y].f)==tp) continue;        if((t[z].ch[0]==y)==(t[y].ch[0]==x)) rot(y);        else rot(x);    }    if(!tp) Root=x;Up(x);}int Kth(int x,int &Root=rt) {    int y=Root,p;    if(x>t[y].sz) return 0;    for(;;) {        pd(y),Up(y),p=t[y].ch[0];        if(t[p].sz+1<x) x-=t[p].sz+1,y=t[y].ch[1];        else if(t[p].sz>=x) y=p; else break;    }    Splay(y,0,Root);    return y;}int Build(int l,int r) {    if(l>r) return 0;    int mid=l+r>>1;    t[mid].ch[0]=Build(l,mid-1);    t[mid].ch[1]=Build(mid+1,r);    t[mid].v=t[mid].mn=a[mid],Up(mid);    if(t[mid].ch[0]) t[t[mid].ch[0]].f=mid;    if(t[mid].ch[1]) t[t[mid].ch[1]].f=mid;    return mid;}inline void Rev(int l,int r) {    int b=Kth(r+2),a=Kth(l);Splay(b,a);    int p=t[b].ch[0];t[p].rev^=1;}inline void Add(int l,int r,int w) {    int b=Kth(r+2),a=Kth(l);Splay(b,a);    int p=t[b].ch[0];t[p].dv+=w,Up(b),Up(a);}inline int QMIN(int l,int r) {    int b=Kth(r+2),a=Kth(l);Splay(b,a);    int p=t[b].ch[0];Up(b),Up(a);    return t[p].mn+t[p].dv;}inline void Merge(int &l,int r) {    int p=rt;    for(;t[p].ch[1];) p=t[p].ch[1];    Splay(p,0,l),t[l].ch[1]=r,t[r].f=l,Up(l);}inline void Split(int &x,int k,int &l,int &r) {    Kth(k,x),l=x,r=t[x].ch[1],t[r].f=0,t[x].ch[1]=0,Up(l);}inline void Revolve(int l,int r,int T) {    (T=T%(r-l+1)+(r-l+1))%=(r-l+1);    if(!T) return;    Rev(l,r),Rev(l,l+T-1),Rev(l+T,r);}void Del(int k) {    int t1,t2,t3;    Split(rt,k,t1,t2),Split(t2,1,t2,t3);    Merge(t1,t3),rt=t1;}void Ins(int k,int x) {    int t1,t2;t[++sz].v=t[sz].mn=x,t[sz].sz=1;    Split(rt,k+1,t1,t2),Merge(t1,sz),Merge(t1,t2),rt=t1;}int main() {    int n,m,l,r,x;char s[10];    in(n),a[1]=a[n+2]=t[0].mn=~0U>>2;    for(int i=1;i<=n;i++) in(a[i+1]);    for(rt=Build(1,n+2),sz=n+4,in(m);m--;) {        scanf("%s",s);        if(s[0]=='A') in(l),in(r),in(x),Add(l,r,x);        else if(s[0]=='M') in(l),in(r),printf("%d\n",QMIN(l,r));        else if(s[0]=='I') in(l),in(r),Ins(l,r);        else if(s[0]=='D') in(x),Del(x);        else if(s[3]=='E') in(l),in(r),Rev(l,r);        else in(l),in(r),in(x),Revolve(l,r,x);    }}

然后让我们来感受一下Splay的终结者(做此题的时候可以适当颓一颓bzoj3223放松一下心情(?)):
bzoj1500
放松心情(?)的Code

#include<cstdio>#define N 200005#define Swap(a,b) tmp=a,a=b,b=tmp#define Up(r) t[r].sz=t[t[r].ch[0]].sz+t[t[r].ch[1]].sz+1int rt,sz,n,m,tmp;struct node {int f,sz,ch[2],rev;} t[N];inline void in(int &x) {    x=0;static char c=' ',f=1;    for(;c<'0'||c>'9';) {if(c=='-') f=-1;c=getchar();}    for(;c>='0'&&c<='9';) x=x*10+c-'0',c=getchar();x*=f;}inline void rot(int x) {    int y=t[x].f,z=t[y].f,f=(t[y].ch[1]==x);    t[y].ch[f]=t[x].ch[!f];    if(t[y].ch[f]) t[t[y].ch[f]].f=y;    t[x].ch[!f]=y,t[y].f=x,t[x].f=z;    if(z) t[z].ch[t[z].ch[1]==y]=x;Up(y);}inline void pd(int x) {    if(!t[x].rev) return;    Swap(t[x].ch[1],t[x].ch[0]);    t[t[x].ch[0]].rev^=1;    t[t[x].ch[1]].rev^=1;    t[x].rev=0;}inline void Splay(int x,int tp) {    for(int y,z;(y=t[x].f)!=tp;rot(x)) {        pd(x);        if((z=t[y].f)==tp) continue;        if((t[z].ch[0]==y)==(t[y].ch[0]==x)) rot(y);        else rot(x);    }    if(!tp) rt=x;Up(x);}inline int Kth(int x) {    int y=rt,p;    if(x>t[rt].sz) return 0;    for(;;) {        pd(y),p=t[y].ch[0];        if(t[p].sz+1<x) x-=t[p].sz+1,y=t[y].ch[1];        else if(t[p].sz>=x) y=p; else return y;    }}inline int Build(int l,int r) {    if(l>r) return 0;    int mid=l+r>>1;    t[mid].ch[0]=Build(l,mid-1);    t[mid].ch[1]=Build(mid+1,r);    Up(mid);t[t[mid].ch[0]].f=t[t[mid].ch[1]].f=mid;    return mid;}inline void Rev(int l,int r) {    int a=Kth(l),b=Kth(r+2);Splay(a,0),Splay(b,a);    int p=t[b].ch[0];t[p].rev^=1;}inline void print(int x) {    if(!x) return;    pd(x),print(t[x].ch[0]);    if(x!=1&&x!=n+2) printf("%d ",x-1);    print(t[x].ch[1]);}int main() {    int l,r;    for(in(n),in(m),rt=Build(1,n+2);m--;) in(l),in(r),Rev(l,r);    print(rt);    return 0;}

感受一下序列之王的终结者Code

#include<cstring>#include<cstdio>#define N 500500#define swap(a,b) tmp=a,a=b,b=tmpint rt,sz,tmp,tot,cnt,a[N],rubbish[N];struct Node {int c,f,v,sz,mc,lc,rc,rev,tag,sum,ch[2];} t[N];inline int max(int a,int b) {return a>b?a:b;}inline void in(int &x) {    x=0;static char c,f;c=' ',f=1;    for(;c<'0'||c>'9';) {if(c=='-') f=-1;c=getchar();}    for(;c>='0'&&c<='9';) x=x*10+c-'0',c=getchar();x*=f;}inline int New() {    if(rubbish[cnt]) return rubbish[cnt--];    else return ++sz;}inline void reve(int x) {    t[x].rev^=1,swap(t[x].lc,t[x].rc);    swap(t[x].ch[0],t[x].ch[1]);}inline void setv(int x,int v) {    t[x].tag=1,t[x].v=v,t[x].sum=v*t[x].sz;    if(v>0) t[x].lc=t[x].rc=t[x].mc=t[x].sum;    else t[x].lc=t[x].rc=0,t[x].mc=v;}inline void pd(int x) {    static int l,r;    l=t[x].ch[0],r=t[x].ch[1];    if(t[x].tag) {        if(l) setv(l,t[x].v);        if(r) setv(r,t[x].v);t[x].tag=t[x].rev=0;    }    if(t[x].rev) {        if(l) reve(l);        if(r) reve(r);t[x].rev=0;    }}inline int Up(int x) {    static int l,r;    l=t[x].ch[0],r=t[x].ch[1];    t[x].sz=t[l].sz+t[r].sz+1;    t[x].sum=t[l].sum+t[r].sum+t[x].v;    t[x].mc=t[l].rc+t[r].lc+t[x].v;    if(l) t[x].mc=max(t[x].mc,t[l].mc);    if(r) t[x].mc=max(t[x].mc,t[r].mc);    t[x].lc=max(t[l].lc,t[l].sum+max(t[r].lc,0)+t[x].v);    t[x].rc=max(t[r].rc,t[r].sum+max(t[l].rc,0)+t[x].v);}inline void rot(int x) {    int y=t[x].f,z=t[y].f,f=(t[y].ch[1]==x);    pd(y),pd(x),t[y].ch[f]=t[x].ch[!f];    if(t[y].ch[f]) t[t[y].ch[f]].f=y;    t[x].ch[!f]=y,t[y].f=x,t[x].f=z;    if(z) t[z].ch[t[z].ch[1]==y]=x;Up(y),Up(x);}inline void Splay(int x,int tp,int &Root=rt) {    for(int y,z;(y=t[x].f)!=tp;rot(x)) {        pd(x);        if((z=t[y].f)==tp) continue;        if((t[z].ch[0]==y)==(t[y].ch[0]==x)) rot(y);        else rot(x);    }    if(!tp) Root=x;Up(x);}inline int Build(int l,int r) {    if(l>r) return 0;    int mid=l+r>>1,x=New();t[x].v=a[mid];    if(l==r) {t[x].sz=1,setv(x,a[mid]),t[x].tag=0;return x;}    t[x].ch[0]=Build(l,mid-1);    t[x].ch[1]=Build(mid+1,r),Up(x);    if(t[x].ch[0]) t[t[x].ch[0]].f=x;    if(t[x].ch[1]) t[t[x].ch[1]].f=x;    return x;}inline int Kth(int x,int &Root=rt) {    int y=Root,p;    if(x>t[Root].sz) return 0;    for(;;) {        pd(y),p=t[y].ch[0];        if(t[p].sz+1<x) x-=t[p].sz+1,y=t[y].ch[1];        else if(t[p].sz>=x) y=p; else break;    }    Splay(y,0,Root);    return y;}inline void Merge(int &l,int r) {    int q=rt;    for(;t[q].ch[1];) q=t[q].ch[1];    Splay(q,0,l),t[l].ch[1]=r,t[r].f=l,Up(l);}inline void Split(int &x,int k,int &l,int &r) {    Kth(k,x),l=x,r=t[x].ch[1],t[r].f=0,t[x].ch[1]=0,Up(l);}inline void Rec(int x) {    if(!x) return;    Rec(t[x].ch[0]),rubbish[++cnt]=x,Rec(t[x].ch[1]);    t[x]=t[0];}inline void Rev(int l,int r) {    int b=Kth(l+r+1),a=Kth(l);Splay(b,a);    int p=t[b].ch[0];reve(p),Up(b),Up(a);}inline void Set(int l,int r,int v) {    int b=Kth(l+r+1),a=Kth(l);Splay(b,a);    int p=t[b].ch[0];setv(p,v),Up(b),Up(a);}inline int Sum(int l,int r) {    int b=Kth(l+r+1),a=Kth(l);Splay(b,a);    return t[t[b].ch[0]].sum;}inline void Del(int l,int r) {    int t1,t2,t3;    Split(rt,l,t1,t2),Split(t2,r,t2,t3);    Rec(t2),Merge(t1,t3),rt=t1;}inline void Ins(int x,int l) {    int t1,t2,p=Build(1,l);Split(rt,x+1,rt,t2);    Merge(rt,p),Merge(rt,t2);}inline void print(int x) {    if(!x) return;    print(t[x].ch[0]);    printf("%d %d %d %d %d %d %d\n",x,t[x].ch[0],t[x].ch[1],t[x].lc,t[x].rc,t[x].mc,t[x].v);    print(t[x].ch[1]);}int main() {    int i,n,m,op,l,r,x;char s[15];    in(n),in(m),a[1]=a[n+2]=-20000;    for(i=2;i<=n+1;++i) in(a[i]);    rt=Build(1,n+2),sz=n+2;    for(;m--;) {        scanf("%s",s);        if(s[0]=='I') {            for(in(x),in(l),i=1;i<=l;++i) in(a[i]);            Ins(x,l);        } else if(s[0]=='D') in(l),in(r),Del(l,r);        else if(s[2]=='K') in(l),in(r),in(x),Set(l,r,x);        else if(s[0]=='R') in(l),in(r),Rev(l,r);        else if(s[0]=='G') in(l),in(r),printf("%d\n",Sum(l,r));        else if(s[2]=='X') printf("%d\n",t[rt].mc);    }}

曰啊曰啊曰啊
我调了10h+啊啊啊啊啊啊啊啊
奇慢无比QwQ

原创粉丝点击