dp啃不动啊 太难了还是数据结构好 但是不思考是会学傻的。。。
先说平衡树吧,treap 还算简单但是我学了一下午真笨。
BST 很好理解 上升的treap 不过是支持旋转罢了,更好的维护平衡的性质罢了。
书上是这样说的我们发现随机下的BST是趋近与平衡的,所以treap是利用随机来创造平衡条件的。
插入操作:在BST中进行查找不在treap中进行检索有相同的数字的话就++;
没有的话在检索到的这个位置生成新的节点并get一个随机值。自底向上进行更新。
利用随机出来的值进行旋转什么的 维护平衡状态:
inline void insert(int &p,int val) { if(p==0) { p=New(val); return; } if(val==val(p)) { ++cnt(p); update(p);return; } if(val<val(p)) { insert(l(p),val); if(dat(p)<dat(l(p)))zig(p); } else { insert(r(p),val); if(dat(p)<dat(r(p)))zag(p); } update(p); }
删除操作:删除x 如果树中没有x不需删除 如果有重复减少副本数即可。
没有的话 看其是不是叶子节点 是的话直接删不是的话向下旋转直到旋转到叶子节点。
inline void re(int &p,int val) { if(p==0)return; if(val==val(p)) { if(cnt(p)>1) { --cnt(p); update(p); return; } if(l(p)||r(p)) { if(r(p)==0||dat(l(p))>dat(r(p))) zig(p),re(r(p),val); else zag(p),re(l(p),val); update(p); } else p=0; return; } val<val(p)?re(l(p),val):re(r(p),val); update(p);return; }
找排名这个好找直接检索即可。
inline int getrankbyval(int p,int val) { if(p==0)return 0; if(val==val(p))return sz(l(p))+1; if(val<val(p))return getrankbyval(l(p),val); return getrankbyval(r(p),val)+sz(l(p))+cnt(p); }
getvalbyrank的话也比较简单注意细节即可
inline int getvalbyrank(int p,int rank) { if(p==0)return INF; if(sz(l(p))>=rank)return getvalbyrank(l(p),rank); if(sz(l(p))+cnt(p)>=rank)return val(p); return getvalbyrank(r(p),rank-sz(l(p))-cnt(p)); }
求x的前驱 其实就是检索x 考虑直接在树中检索x 遇到的都是比x小或比x大的节点不断的去检索x那么此时更新大答案即可。
出现x这个的话那么前驱其实就是x的左子树的最右边的儿子了。
inline int getpre(int val) { int ans=1,p=root; while(p) { if(val==val(p)) { if(l(p)>0) { p=l(p); while(r(p))p=r(p); ans=p; } break; } if(val(p)<val&&val(p)>val(ans))ans=p; p=val<val(p)?l(p):r(p); } return val(ans); }
至于求后继和求前驱其实是一样的。
inline int getnext(int val) { int ans=2,p=root; while(p) { if(val==val(p)) { if(r(p)) { p=r(p); while(l(p))p=l(p); ans=p; } break; } if(val(p)>val&&val(p)<val(ans))ans=p; p=val<val(p)?l(p):r(p); } return val(ans); }
完整代码:
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<iomanip> #include<cstring> #include<string> #include<cstdlib> #include<cmath> #include<algorithm> #include<cctype> #include<utility> #include<set> #include<bitset> #include<queue> #include<stack> #include<deque> #include<map> #include<vector> #include<ctime> #define INF 2147483646 #define ll long long #define max(x,y) (x>y?x:y) #define min(x,y) (x>y?y:x) #define l(x) t[x].l #define r(x) t[x].r #define val(x) t[x].val #define dat(x) t[x].dat #define cnt(x) t[x].cnt #define sz(x) t[x].sz using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } inline void put(int x) { x<0?putchar('-'),x=-x:0; int num=0;char ch[50]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar(' ');return; } //平衡树->splay Author:chdy const int MAXN=100010; int n,root,tot; struct wy { int l,r; int val,dat; int cnt,sz; }t[MAXN]; inline int New(int val) { val(++tot)=val; dat(tot)=rand(); cnt(tot)=sz(tot)=1; return tot; } inline void update(int p) { sz(p)=sz(l(p))+sz(r(p))+cnt(p); return; } inline void build() { New(-INF);New(INF); root=1;r(1)=2; update(root); } inline int getrankbyval(int p,int val) { if(p==0)return 0; if(val==val(p))return sz(l(p))+1; if(val<val(p))return getrankbyval(l(p),val); return getrankbyval(r(p),val)+sz(l(p))+cnt(p); } inline int getvalbyrank(int p,int rank) { if(p==0)return INF; if(sz(l(p))>=rank)return getvalbyrank(l(p),rank); if(sz(l(p))+cnt(p)>=rank)return val(p); return getvalbyrank(r(p),rank-sz(l(p))-cnt(p)); } inline void zig(int &p)//右旋 { int q=l(p); l(p)=r(q);r(q)=p;p=q; update(r(p));update(p); } inline void zag(int &p) { int q=r(p); r(p)=l(q);l(q)=p;p=q; update(l(p));update(p); } inline void insert(int &p,int val) { if(p==0) { p=New(val); return; } if(val==val(p)) { ++cnt(p); update(p);return; } if(val<val(p)) { insert(l(p),val); if(dat(p)<dat(l(p)))zig(p); } else { insert(r(p),val); if(dat(p)<dat(r(p)))zag(p); } update(p); } inline int getpre(int val) { int ans=1,p=root; while(p) { if(val==val(p)) { if(l(p)>0) { p=l(p); while(r(p))p=r(p); ans=p; } break; } if(val(p)<val&&val(p)>val(ans))ans=p; p=val<val(p)?l(p):r(p); } return val(ans); } inline int getnext(int val) { int ans=2,p=root; while(p) { if(val==val(p)) { if(r(p)) { p=r(p); while(l(p))p=l(p); ans=p; } break; } if(val(p)>val&&val(p)<val(ans))ans=p; p=val<val(p)?l(p):r(p); } return val(ans); } inline void re(int &p,int val) { if(p==0)return; if(val==val(p)) { if(cnt(p)>1) { --cnt(p); update(p); return; } if(l(p)||r(p)) { if(r(p)==0||dat(l(p))>dat(r(p))) zig(p),re(r(p),val); else zag(p),re(l(p),val); update(p); } else p=0; return; } val<val(p)?re(l(p),val):re(r(p),val); update(p);return; } int main() { //freopen("1.in","r",stdin); build(); n=read(); for(int i=1;i<=n;++i) { int p,x; p=read();x=read(); switch(p) { case 1:insert(root,x); break; case 2:re(root,x); break; case 3:put(getrankbyval(root,x)-1); break; case 4:put(getvalbyrank(root,x+1)); break; case 5:put(getpre(x)); break; case 6:put(getnext(x)); break; } } return 0; }
还有splay 听说学过它之后就能搞LCT了 真棒但是先放下去搞dp去留坑这里。