splay的模版
来源:互联网 发布:网络电视卡顿怎么办 编辑:程序博客网 时间:2024/06/13 02:34
#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define MAXN 100010struct Node{ int key, sz, cnt; //cnt表示结点值为key的结点的数量 Node *ch[2], *pnt;//左右儿子和父亲 Node(){} //给Node函数赋值。 Node(int x, int y, int z){ key = x, sz = y, cnt = z; } void rs(){//这个函数的含义就是旋转后,这2个结点的大小已经发生了改变 sz = ch[0]->sz + ch[1]->sz + cnt; }}nil(0, 0, 0), *NIL = &nil;struct Splay{//伸展树结构体类型 Node *root; int ncnt;//计算key值不同的结点数,注意已经去重了* Node nod[MAXN]; void init(){// 首先要初始化* root = NIL; ncnt = 0; } void rotate(Node *x, bool d){//旋转操作,d为true表示右旋 Node *y = x->pnt; y->ch[!d] = x->ch[d];//x右旋的时候,y的左儿子为x的右边儿 if (x->ch[d] != NIL)//如果x的右儿子不为空那么这个右儿子的父亲是y x->ch[d]->pnt = y; x->pnt = y->pnt;//把y的父亲赋值给x的父亲,相当x替代了y的位子 if (y->pnt != NIL){//把y的父亲的左儿子或右儿子从y改为x if (y == y->pnt->ch[d]) y->pnt->ch[d] = x; else y->pnt->ch[!d] = x; } x->ch[d] = y; y->pnt = x; y->rs(); x->rs(); } void splay(Node *x, Node *target){//将x伸展到target的儿子位置处 Node *y; while (x->pnt != target){ //当target时,就转x为根结点 y = x->pnt; if (x == y->ch[0]){ if (y->pnt != target && y == y->pnt->ch[0])//如果x是y的左结点,且y的父亲结点不是目标结点 rotate(y, true);//并且y是y的左结点才旋转y否则旋转x rotate(x, true); } else{ if (y->pnt != target && y == y->pnt->ch[1]) rotate(y, false); rotate(x, false); } } if (target == NIL) root = x; } /************************以上一般不用修改************************/ void insert(int key){//插入一个值 if (root == NIL){//初始化根节点 ncnt = 0; root = &nod[++ncnt]; root->ch[0] = root->ch[1] = root->pnt = NIL; root->key = key; //这里表示这个结点的值 root->sz = root->cnt = 1;//sz表示这个结点作为根的大小 return; } Node *x = root, *y; while (1){ //从x开始向下找,刚开始x就是root x->sz++; if (key == x->key){ x->cnt++; x->rs(); y = x; break; } else if (key < x->key){//这里表示如果新加入的值比x小,且左结点为空,那么就加入其作为左儿子 if (x->ch[0] != NIL)//否则接着往左边找 x = x->ch[0]; else{//且左结点为空,那么就加入其作为左儿子 x->ch[0] = &nod[++ncnt]; y = x->ch[0];//新加入的点为y y->key = key; y->sz = y->cnt = 1;//y的刚开始大小为1 y->ch[0] = y->ch[1] = NIL;//左右子树均为NIL y->pnt = x;// break; } } else{ if (x->ch[1] != NIL) x = x->ch[1]; else{ x->ch[1] = &nod[++ncnt]; y = x->ch[1]; y->key = key; y->sz = y->cnt = 1; y->ch[0] = y->ch[1] = NIL; y->pnt = x; break; } } } splay(y, NIL); } Node* search(int key){//查找一个值并且把这个值旋上来,返回指针 if (root == NIL) return NIL; Node *x = root, *y = NIL; while (1){ if (key == x->key){ y = x; break; } else if (key > x->key){ if (x->ch[1] != NIL) x = x->ch[1]; else break; } else{ if (x->ch[0] != NIL) x = x->ch[0]; else break; } } splay(x, NIL); return y; } Node* searchmin(Node *x){//查找最小值,返回指针 Node *y = x->pnt; while (x->ch[0] != NIL){//遍历到最左的儿子就是最小值 x = x->ch[0]; } splay(x, y); return x; } void del(int key){//删除一个值 if (root == NIL) return; Node *x = search(key), *y; if (x == NIL) return; if (x->cnt > 1){ //如果这个结点还有,那么它就变成根结点 x->cnt--; x->rs(); return; } else if (x->ch[0] == NIL && x->ch[1] == NIL){ //这个是最后一个结点 init(); return; } else if (x->ch[0] == NIL){ root = x->ch[1]; x->ch[1]->pnt = NIL; return; } else if (x->ch[1] == NIL){ root = x->ch[0]; x->ch[0]->pnt = NIL; return; } y = searchmin(x->ch[1]); y->pnt = NIL; y->ch[0] = x->ch[0]; x->ch[0]->pnt = y; y->rs(); root = y; } int rank(int key){//???这里看不懂,求结点高度 Node *x = search(key); if (x == NIL) return 0; return x->ch[0]->sz + 1;/* or x->cnt*/ } Node* findk(int kth){//查找第k小的值 if (root == NIL || kth > root->sz) return NIL; Node *x = root; while (1){ if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt) break; else if (kth <= x->ch[0]->sz) x = x->ch[0]; else{ kth -= x->ch[0]->sz + x->cnt; x = x->ch[1]; } } splay(x, NIL); return x; }}sp;int main(){ //每次sp的返回都是一个指针 sp.init(); sp.insert(10); sp.insert(2); sp.insert(2); sp.insert(2); sp.insert(3); sp.insert(3); sp.insert(10); for (int i = 1; i <= 7; i++) cout << sp.findk(i)->key << endl; cout<< "最小值是"<<sp.searchmin(sp.root)->key<<endl; sp.del(2); sp.del(3); sp.del(1); cout << "不同结点的数量"<<sp.ncnt << endl; cout << "这棵树的大小 " << sp.root->sz << endl; return 0;}
这个代码是一个模版。
下面是区间求最大值,反转
#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int N=100005, INF=0x7fffffff;struct Splay_Tree { struct Node { int val, Max, add, Size, son[2]; bool rev; void init(int _val) { val=Max=_val, Size=1; add=rev=son[0]=son[1]=0; } } T[N]; int fa[N], root; void pushUp(int x) { T[x].Max=T[x].val, T[x].Size=1; if(T[x].son[0]) { T[x].Max=max(T[x].Max, T[T[x].son[0]].Max); T[x].Size+=T[T[x].son[0]].Size; } if(T[x].son[1]) { T[x].Max=max(T[x].Max, T[T[x].son[1]].Max); T[x].Size+=T[T[x].son[1]].Size; } } void pushDown(int x) { if(x==0) return; if(T[x].add) { if(T[x].son[0]) { T[T[x].son[0]].val+=T[x].add; T[T[x].son[0]].Max+=T[x].add; T[T[x].son[0]].add+=T[x].add; } if(T[x].son[1]) { T[T[x].son[1]].val+=T[x].add; T[T[x].son[1]].Max+=T[x].add; T[T[x].son[1]].add+=T[x].add; } T[x].add=0; } if(T[x].rev) { if(T[x].son[0]) T[T[x].son[0]].rev^=1; if(T[x].son[1]) T[T[x].son[1]].rev^=1; swap(T[x].son[0], T[x].son[1]); T[x].rev=0; } } void Rotate(int x, int kind) { int y=fa[x], z=fa[y]; T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y; T[x].son[kind]=y, fa[y]=x; T[z].son[T[z].son[1]==y]=x, fa[x]=z; pushUp(y); } void Splay(int x, int goal) { if(x==goal) return; while(fa[x]!=goal) { int y=fa[x], z=fa[y]; pushDown(z), pushDown(y), pushDown(x); int rx=T[y].son[0]==x, ry=T[z].son[0]==y; if(z==goal) Rotate(x, rx); else { if(rx==ry) Rotate(y, ry); else Rotate(x, rx); Rotate(x, ry); } } pushUp(x); if(goal==0) root=x; } int Select(int pos) { int u=root; pushDown(u); while(T[T[u].son[0]].Size!=pos) { if(pos<T[T[u].son[0]].Size) u=T[u].son[0]; else { pos-=T[T[u].son[0]].Size+1; u=T[u].son[1]; } pushDown(u); } return u; } void update(int L, int R, int val) { int u=Select(L-1), v=Select(R+1); Splay(u, 0); Splay(v, u); T[T[v].son[0]].Max+=val; T[T[v].son[0]].val+=val; T[T[v].son[0]].add+=val; } void Reverse(int L, int R) { int u=Select(L-1), v=Select(R+1); Splay(u, 0); Splay(v, u); T[T[v].son[0]].rev^=1; } int query(int L, int R) { int u=Select(L-1), v=Select(R+1); Splay(u, 0); Splay(v, u); return T[T[v].son[0]].Max; } int build(int L, int R) { if(L>R) return 0; if(L==R) return L; int mid=(L+R)>>1, sL, sR; T[mid].son[0]=sL=build(L, mid-1); T[mid].son[1]=sR=build(mid+1, R); fa[sL]=fa[sR]=mid; pushUp(mid); return mid; } void init(int n) { T[0].init(-INF), T[1].init(-INF), T[n+2].init(-INF); for(int i=2; i<=n+1; i++) T[i].init(0); root=build(1, n+2), fa[root]=0; fa[0]=0, T[0].son[1]=root, T[0].Size=0; }};Splay_Tree hehe;int main() { int n, m; scanf("%d%d", &n, &m); hehe.init(n); for(int i=0, a, b, c, d; i<m; i++) { scanf("%d", &a); if(a==1) { scanf("%d%d%d", &b, &c, &d); hehe.update(b, c, d); } else if(a==2) { scanf("%d%d", &b, &c); hehe.Reverse(b, c); } else { scanf("%d%d", &b, &c); printf("%d\n", hehe.query(b, c)); } } return 0;}
阅读全文
0 0
- splay的模版
- splay模版
- splay模版
- Splay 模版
- 自己的splay模版(bzoj1588)
- Splay——kuangnin的模版
- splay树模版
- Splay树模版
- 开学splay(这个模版要背的滚瓜烂熟)
- HNOI 2000 Splay Tree 模版题目
- [BZOJ 1588]营业额统计 && splay部分模版
- Splay tree的splay操作
- wikioi-1296-营业额统计-----------学习splay tree模版题
- Splay的常数问题
- 郁闷的出纳员 ( splay )
- KWY的splay总结
- [Splay的应用]
- splay树的实现
- 编译安装nginx
- 筛法,欧拉函数表,莫比乌斯函数表,积性函数
- ecplise之SpringBoot热部署
- 计算机网格---网关,广播地址,网段地址,子码掩码
- ios开发:Xcode8制作framework及使用
- splay的模版
- 学习笔记-Android屏幕适配最棒的解决方案
- 业余时间决定了你的人生
- RabbitMQ与spring集成,配置完整的生产者和消费者
- c++中指针与引用的
- 最短路算法 摘要
- BinarySearch-----279. Perfect Squares
- 文章标题
- 高级Java程序员要具备哪些知识