洛谷 2596 无旋treap

6 篇文章 0 订阅

luogu 2596

题意比较好看懂吧?

我们知道无旋treap无法去查找第几个 所以看了大佬的思路 用爸爸去查找

真的是太无敌了 这个想法 

其他几个操作都想到了 这个爸爸思路也太牛啤了吧

/*
luogu 2596
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <set>
#include <iostream>
#include <stdlib.h>
#include <sstream>
#define dbg(x) ;
const int MAX_N = 500010;

int siz[MAX_N],ch[MAX_N][2],rnd[MAX_N],val[MAX_N],id[MAX_N],fa[MAX_N],a[MAX_N];
int T,cnt,m,p,root;
int r1,r2,r3,r4;

int read(){
    int x = 0,f = 1;char c = getchar();
    while(c>'9'||c<'0') {if(c=='-') f = -1; c= getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}
void update(int now){
    siz[now] =  1 + siz[ch[now][0]] + siz[ch[now][1]];
}

int Insert(int a){
    siz[++cnt] = 1;
    val[cnt] = a;
    rnd[cnt] = rand();
    id[a] = cnt;
    return cnt;
}

int Merge(int A,int B){
    if(!A||!B) return A + B;
    if(rnd[A]<rnd[B]) {ch[A][1] = Merge(ch[A][1],B);fa[ch[A][1]] = A;update(A);return A;}
    else {ch[B][0] = Merge(A,ch[B][0]);fa[ch[B][0]] = B;update(B);return B;}
}

void split(int now,int k,int &x,int &y,int faa = 0,int fab = 0){
    if(!now) x = y = 0;
    else {
            if(k<=siz[ch[now][0]]) {fa[now] = fab;y = now;split(ch[now][0],k,x,ch[now][0],faa,now);}
        else {fa[now] = faa;x = now;split(ch[now][1],k-siz[ch[now][0]]-1,ch[now][1],y,now,fab);}update(now);}
}

void Ins(int pos,int v){
        split(root,pos,r1,r2);
        root = Merge(r1,Merge(Insert(v),r2));
}
bool Get(int x) {
    return ch[fa[x]][1]==x;}

int Find(int cnt){
    int node = cnt,res = siz[ch[cnt][0]] + 1;
    while(node!=root&&cnt){
        dbg(cnt);
        if(Get(cnt)) res+=siz[ch[fa[cnt]][0]]+1;
        cnt = fa[cnt];
    }
    return res;
}

int main(){
    int n;
    n = read(), m =read();
    int X;
    for(int i = 1;i<=n;++i){
        a[i] = read();
        Ins(i-1,a[i]);
    }
    for(int i = 1;i<=n;++i)
        dbg(Find(a[i]));
    //dbg(root);
    char opt[20];
    int x,k,y;
    for(int i=1;i<=m;i++){
        scanf("%s", opt); x = read();

        if(opt[0] == 'T'){
            k = Find(id[x]);//通过节点编号找到书本编号为x的节点是第k个
            split(root, k, r1, r3);
            split(r1, k-1, r1, r2);
            root = Merge(r2, Merge(r1, r3));
        }

        if(opt[0] == 'B'){
            k = Find(id[x]);
            split(root, k, r1, r3, 0);
            split(r1, k-1, r1, r2, 0);
            root = Merge(r1, Merge(r3, r2));
        }

        if(opt[0] == 'I'){
            y = read(); k = Find(id[x]);
            if(y){
                if(y > 0){//与前驱/后继交换后插入
                    split(root, k+1, r3, r4);
                    split(r3, k, r2, r3);
                    split(r2, k-1, r1, r2);
                    root = Merge(r1, Merge(r3, Merge(r2, r4)));
                }
                else {
                    split(root, k, r3, r4);
                    split(r3, k-1, r2, r3);
                    split(r2, k-2, r1, r2);
                    root = Merge(r1, Merge(r3, Merge(r2, r4)));
                }
            }
        }

        if(opt[0] == 'A'){
            k = Find(id[x]);
            printf("%d\n", k-1);
        }

        if(opt[0] == 'Q'){
            split(root, x, r1, r2);
            int node = r1;
            while(ch[node][1]) node = ch[node][1];
            printf("%d\n", val[node]);
            root = Merge(r1, r2);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值