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
放松心情(?)的
#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;}
感受一下序列之王的终结者的
#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
阅读全文
0 0
- Splay到吐血
- 熬夜到吐血-D2
- 吐血
- 吐血
- 2007终于发布了!累到吐血...
- [吐血推荐]Ajax从入门到精通!!
- GNUI30天从入门到吐血
- 研究DRBL到吐血的心路历程
- SPLAY
- splay
- splay
- splay
- Splay
- Splay
- splay
- splay
- splay
- splay
- 插入排序(INSERTION-SORT)
- BZOJ 2152:聪聪可可
- Django-ORM多对多查询 (自定义第三张表&ManyToManyField)
- JZOJ__Day 2:【NOIP普及模拟】分数
- 5-3 奥运排行榜 (25分)
- Splay到吐血
- 自定义UI
- 图片的自动轮换
- 运行时间和当前时间比较,距离现在时间的分钟数。
- 5-4 PAT排名汇总 (25分)
- 端口分类调研
- 日期格式的转化
- 常用的Hql语句
- Centos7 关闭防火墙