treap 93pts第一个点WA求调
查看原帖
treap 93pts第一个点WA求调
558324
AutiFancers楼主2023/9/22 20:20
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=100010,INF=0x7fffffff;

struct node{
   int ls,rs;
   int val,dat;
   int cnt,size; 
}tr[N];//数组模拟链表
int n,root,idx;//idx代表当前分配到了第个节点,root代表根节点

int get_node(int k){
    tr[++idx].val=k;
    tr[idx].dat=rand();
    tr[idx].cnt=tr[idx].size=1;
    return idx;
}

void update(int u){
    tr[u].size=tr[tr[u].ls].size+tr[tr[u].rs].size+tr[u].cnt;
}

void build(){
    get_node(-INF),get_node(INF);//两个哨兵
    root=1,tr[1].rs=2;//自定义将根节点定为1也就是-INF,将根节点的右儿子定为2也就是-INF
    update(root);
}

int getrankbyval(int u,int val){
    if(u==0) return 0;
    if(val==tr[u].val) return tr[tr[u].ls].size+1;
    if(val<tr[u].val) return getrankbyval(tr[u].ls,val);
    return getrankbyval(tr[u].rs,val)+tr[tr[u].ls].size+tr[u].cnt;
}

int getvalbyrank(int u,int rank){
    if(u==0) return INF;
    if(tr[tr[u].ls].size>=rank) return getvalbyrank(tr[u].ls,rank);
    if(tr[tr[u].ls].size+tr[u].cnt>=rank) return tr[u].val;
    return getvalbyrank(tr[u].rs,rank-tr[tr[u].ls].size-tr[u].cnt);
}

void zig(int &p){
    int q=tr[p].ls;
    tr[p].ls=tr[q].rs,tr[q].rs=p,p=q;
    update(tr[p].rs),update(p);
}

void zag(int &p){
    int q=tr[p].rs;
    tr[p].rs=tr[q].ls,tr[q].ls=p,p=q;
    update(tr[p].ls),update(p);
}

void insert(int &u,int val){
    if(u==0){
        u=get_node(val);
        return;
    }

    if(val==tr[u].val){
        tr[u].cnt++,update(u);
        return;
    }

    if(val<tr[u].val){
        insert(tr[u].ls,val);
        if(tr[u].dat<tr[tr[u].ls].dat) zig(u);//不满足堆性质,右旋
    }

    else{
        insert(tr[u].rs,val);
        if(tr[u].dat<tr[tr[u].rs].dat) zag(u);//不满足堆性质,左旋
    }
    update(u);
}

void remove(int &u,int val){
    if(u==0) return;
    if(val==tr[u].val){//搜索到了val
        if(tr[u].cnt>1){
            tr[u].cnt--,update(u);
            return;
        }
        if(tr[u].ls || tr[u].rs){//不是叶节点
            if(tr[u].rs==0 || tr[tr[u].ls].dat>tr[u].dat)
                zig(u),remove(tr[u].rs,val);//右旋过后,u的右儿子就变成了原来的u
            else
                zag(u),remove(tr[u].ls,val);
            update(u);
        }
        else u=0;
        return;
    }
    val<tr[u].val ? remove(tr[u].ls,val) : remove(tr[u].rs,val);//判断是往左边删还是往右边删
    update(u);
}

int getpre(int val){
    int ans=1;
    int u=root;
    while(u){
        if(val==tr[u].val){//搜索到了val
            if(tr[u].ls>0){
                u=tr[u].ls;
                while(tr[u].rs>0) u=tr[u].rs;//左子树上一直向右走
                ans=u;
            }
            break;
        }
        if(tr[u].val<val/*先判断有没有超过val的界限*/ && tr[u].val>tr[ans].val/*取max*/) ans=u;
        u=val<tr[u].val ? tr[u].ls : tr[u].rs; 
    }
    return tr[ans].val;
}

int getnext(int val){
    int ans=2;
    int u=root;
    while(u){
        if(val==tr[u].val){//搜索到了val
            if(tr[u].rs>0){
                u=tr[u].rs;
                while(tr[u].ls>0) u=tr[u].ls;//右子树上一直向左走
                ans=u;
            }
            break;
        }
        if(tr[u].val>val/*先判断有没有超过val的界限*/ && tr[u].val<tr[ans].val/*取max*/) ans=u;
        u=val<tr[u].val ? tr[u].ls : tr[u].rs;
    }
    return tr[ans].val;
}

int main(){
    build();
    scanf("%d",&n);
    while(n--){
        int op,x;
        scanf("%d%d",&op,&x);
        switch(op){
        case 1:
            insert(root,x);
            break;
        case 2:
            remove(root,x);
            break;
        case 3:
            printf("%d\n",getrankbyval(root,x)-1);
            break;
        case 4:
            printf("%d\n",getvalbyrank(root,x+1));
            break;
        case 5:
            printf("%d\n",getpre(x));
            break;
        default:
            printf("%d\n",getnext(x));
        }
    }
	return 0;
} 

2023/9/22 20:20
加载中...