Splay树模板

来源:互联网 发布:淘宝推广佣金 编辑:程序博客网 时间:2024/06/08 11:11
#include<bits/stdc++.h>#define root_right ch[root][1]using namespace std;const int MX = 4e5 + 5;int a[MX], S[MX], n;int root, rear;         //根节点,节点总数int rem[MX], tot;       //经过删除后未被使用的节点int ch[MX][2], fa[MX];int val[MX], sum[MX][2];int sta[MX];int sz[MX];int gcd(int a, int b) {    return b ? gcd(b, a % b) : a;}void NewNode(int &rt, int father, int v, int s) {    if (tot) rt = rem[tot--];    else rt = ++rear;    fa[rt] = father;    ch[rt][0] = ch[rt][1] = 0;    val[rt] = v;    sta[rt] = s;    sum[rt][s] = v;    sum[rt][s ^ 1] = 0;    sz[rt] = 1;}void PushUP(int rt) {    int ls = ch[rt][0], rs = ch[rt][1];    sz[rt] = sz[ls] + sz[rs] + 1;    sum[rt][0] = gcd(sum[ls][0], sum[rs][0]);    sum[rt][1] = gcd(sum[ls][1], sum[rs][1]);    if (sta[rt] == 0) sum[rt][0] = gcd(sum[rt][0], val[rt]);    else sum[rt][1] = gcd(sum[rt][1], val[rt]);}void build(int &rt, int l, int r, int father) {    if (l > r) return;    int m = (l + r) >> 1;    NewNode(rt, father, a[m], S[m]);    build(ch[rt][0], l, m - 1, rt);    build(ch[rt][1], m + 1, r, rt);    PushUP(rt);}void init() {    root = rear = tot = 0;    NewNode(root, 0, 0, 0);  //一共n+2个节点    NewNode(ch[root][1], root, 0, 0);    for (int i = 1; i <= n; i++) scanf("%d%d", &a[i], &S[i]);    build(ch[ch[root][1]][0], 1, n, ch[root][1]);    PushUP(root);}void Rotate(int rt, int op) { //op=0表示左旋,op=1表示右旋    int father = fa[rt];    //PushDown(father); PushDown(rt);    ch[father][!op] = ch[rt][op];    fa[ch[rt][op]] = father;    if (fa[father])        ch[fa[father]][ch[fa[father]][1] == father] = rt;    fa[rt] = fa[father];    ch[rt][op] = father;    fa[father] = rt;    PushUP(father);  //father变成子节点,只要更新father}void Splay(int rt, int f) {    //PushDown(rt);    while (fa[rt] != f) {        int father = fa[rt];        if (fa[father] == f) Rotate(rt, ch[father][0] == rt);        else {            int gf = fa[father];            if (ch[gf][0] == father) {                if (ch[father][0] == rt) Rotate(father, 1), Rotate(rt, 1);                else Rotate(rt, 0), Rotate(rt, 1);            } else {                if (ch[father][1] == rt) Rotate(father, 0), Rotate(rt, 0);                else Rotate(rt, 1), Rotate(rt, 0);            }        }    }    PushUP(rt);   //更新rt    if (f == 0) root = rt;}int get_kth(int rt, int k) {    int t = sz[ch[rt][0]] + 1, ret;    if (t == k) ret = rt;    else if (t > k) ret = get_kth(ch[rt][0], k);    else ret = get_kth(ch[rt][1], k - t);    return ret;}int Query(int L, int R, int s) {    Splay(get_kth(root, L), 0);      //将第L-1个数旋转到根节点    Splay(get_kth(root, R + 2), root); //将第R+1个数旋转到根节点的右儿子    int ans = sum[ch[ch[root][1]][0]][s];    return ans == 0 ? -1 : ans;}void Insert(int p, int v, int s) {    Splay(get_kth(root, p + 1), 0); //将第p个数旋转到根节点    Splay(get_kth(root, p + 2), root); //将第p+1个数旋转到根节点的右儿子,此时该节点没有左儿子    NewNode(ch[ch[root][1]][0], ch[root][1], v, s);    PushUP(ch[root][1]);    PushUP(root);}void erase(int rt) {    if (!rt)return;    fa[rt] = 0;    rem[++tot] = rt;    erase(ch[rt][0]);    erase(ch[rt][1]);}void Delete(int p) {    Splay(get_kth(root, p), 0);       //将第p-1个数旋转到根节点    Splay(get_kth(root, p + 2), root);//将第p+1个数旋转到根节点的右儿子,此时该节点左儿子为p    erase(ch[ch[root][1]][0]);    ch[ch[root][1]][0] = 0;    PushUP(ch[root][1]);    PushUP(root);}void Change1(int p) {    Splay(get_kth(root, p + 1), 0);   //将第p个数旋转到根节点    sta[root] ^= 1;    PushUP(root);}void Change2(int p, int v) {    Splay(get_kth(root, p + 1), 0);   //将第p个数旋转到根节点    val[root] = v;    PushUP(root);}int main() {    //freopen("in.txt", "r", stdin);    int m, l, r, v, s, p; char op[2];    while (~scanf("%d%d", &n, &m)) {        init();        while (m--) {            scanf("%s", op);            if (op[0] == 'Q') {                scanf("%d%d%d", &l, &r, &s);                printf("%d\n", Query(l, r, s));            }            if (op[0] == 'I') {                scanf("%d%d%d", &p, &v, &s);                Insert(p, v, s);            }            if (op[0] == 'D') {                scanf("%d", &p);                Delete(p);            }            if (op[0] == 'R') {                scanf("%d", &p);                Change1(p);            }            if (op[0] == 'M') {                scanf("%d%d", &p, &v);                Change2(p, v);            }        }    }    return 0;}

原创粉丝点击