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;}


原创粉丝点击