ZOJ 3765 Lights (SPLAY)

本文提供了一个Splay树的数据结构实现代码,包括节点旋转、查找等核心操作,并通过一系列指令进行节点插入、删除及属性修改等功能,适用于动态数据管理。

splay。只为了贴代码保存,没用其他作用。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 500007
#define inf  1000000000
struct Node{
    Node *fa,*ch[2];
    int val,gcd[2],size,statu;
};
Node pool[maxn];
Node *nil;
int cnt = 0;
int gcd(int a,int b){
    if(b <= 0) return a;
    return gcd(b,a%b);
}
void init(){
    cnt = 1;
    nil = pool;
    nil->size = 0;
    nil->fa = nil;
    nil->gcd[0] = nil->gcd[1] = -1;
}
Node *newnode(int val,int statu,Node *f){
    pool[cnt].fa = f;
    pool[cnt].ch[0]=pool[cnt].ch[1]=nil;
    pool[cnt].val = val;
    pool[cnt].size = 1;
    pool[cnt].gcd[statu] = val;
    pool[cnt].gcd[!statu] = -1;
    pool[cnt].statu = statu;
    return &pool[cnt++];
}

//splay向上更新信息******
void update(Node *x){
    x->size = x->ch[0]->size + x->ch[1]->size + 1;
    int statu = x->statu;
    x->gcd[statu] = x->val;
    x->gcd[!statu] = -1;
    if(x->ch[0] != nil){
        x->gcd[0] = gcd(x->ch[0]->gcd[0],x->gcd[0]);
        x->gcd[1] = gcd(x->ch[0]->gcd[1],x->gcd[1]);
    }
    if(x->ch[1] != nil){
        x->gcd[0] = gcd(x->ch[1]->gcd[0],x->gcd[0]);
        x->gcd[1] = gcd(x->ch[1]->gcd[1],x->gcd[1]);
    }
}

//将结点x旋转至splay中父亲的位置******
void rotate(Node *x){
    Node *f = x->fa, *ff = f->fa;
    int t = (f->ch[1] == x);
    if(ff != nil)
        ff->ch[ff->ch[1] == f] = x;
    x->fa = ff;
    f->ch[t] = x->ch[t^1];
    x->ch[t^1]->fa = f;
    x->ch[t^1] = f;
    f->fa = x;
    update(f);
}
//将结点x旋转至x所在splay的根位置******
void splay(Node *x,Node *end){
    Node *f, *ff;
    while(x->fa!=end){
        f = x->fa,ff = f->fa;
        if(f->fa != end)
            if((ff->ch[1]==f)&&(f->ch[1] == x))
                rotate(f);
            else rotate(x);
        rotate(x);
    }
    update(x);
}

Node*find(int k,Node *root){
    if(root->ch[0]->size == k-1) return root;
    if(root->ch[0]->size >= k)
        return find(k,root->ch[0]);
    return find(k-root->ch[0]->size-1,root->ch[1]);
}

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        Node* root = newnode(-1,0,nil);
        Node* left,*right;
        int l,r,u,statu,val;
        char x[2];
        for(int i = 0;i < n; i++){
            scanf("%d%d",&val,&statu);
            left = newnode(val,statu,root);
            root->ch[1] = left;
            splay(left,nil);
            root = left;
        }
        left = newnode(-1,0,root);
        root->ch[1] = left;
        splay(left,nil);
        root = left;
        while(m--){
            scanf("%s",x);
            if(x[0] == 'Q'){
                scanf("%d%d%d",&l,&r,&statu);
                root = find(l,root);
                splay(root,nil);
                right = find(r+2,root);
                splay(right,root);
                printf("%d\n",right->ch[0]->gcd[statu]);
            }
            else if(x[0] == 'I'){
                scanf("%d%d%d",&l,&val,&statu);
                root = find(l+1,root);
                splay(root,nil);
                right = newnode(val,statu,root);
                right->ch[1] = root->ch[1];
                root->ch[1]->fa = right;
                root->ch[1] = right;
                update(right);
                splay(right,nil);
                root = right;
            }
            else if(x[0] == 'D'){
                scanf("%d",&l);
                root = find(l,root);
                splay(root,nil);
                right = find(l+2,root);
                splay(right,root);
                right->ch[0] = nil;
                splay(root=right,nil);
            }
            else if(x[0] == 'R'){
                scanf("%d",&l);
                root = find(l+1,root);
                splay(root,nil);
                root->statu = !root->statu;
                update(root);
            }
            else if(x[0] == 'M'){
                scanf("%d%d",&l,&val);
                root = find(l+1,root);
                splay(root,nil);
                root->val = val;
                update(root);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值