救救我吧,有wa有tle

P6136 【模板】普通平衡树(数据加强版)

BHH985211 @ 2024-09-28 20:28:50

#include<bits/stdc++.h>
using namespace std;
struct node{
    int s[2];//左右儿子 
    int p;//父亲 
    int v;//节点数值
    int cnt;//出现几次
    int size;//子树大小
    void init(int p1,int v1){
        p=p1,v=v1;
        cnt=size=1;
    } 
}tr[2000005];
int root,idx;//根节点编号,节点个数
void pushup(int x)
{
    tr[x].size=tr[tr[x].s[0]].size+tr[tr[x].s[1]].size+tr[x].cnt;
}
void rotate(int x)
{
    int y=tr[x].p,z=tr[y].p;//y父亲z爷爷
    int k=tr[y].s[1]==x;//K记录x是y的左or右节点
    tr[y].s[k]=tr[x].s[k^1]; 
    tr[tr[x].s[k^1]].p=y;
    tr[x].s[k^1]=y;
    tr[y].p=x;
    tr[z].s[tr[z].s[1]==y]=x;
    tr[x].p=z;
    pushup(y),pushup(x); 
}
void splay(int x,int k)//将x移到k下 
{
    while(tr[x].p!=k){//x的父亲等于k结束 
        int y=tr[x].p,z=tr[y].p;
        if(z!=k) (tr[y].s[0]==x)^(tr[z].s[0]==y)? rotate(x):rotate(y);//直线型转中间节点 
        rotate(x);
    }
    if(k==0) root=x;
}
void insert(int v)
{
    int x=root,p=0;//x来移动,p是父节点
    while(x&&tr[x].v!=v)
        p=x,x=tr[x].s[v>tr[x].v];
    if(x) tr[x].cnt++;
    else{
        x=++idx;
        tr[p].s[v>tr[p].v]=x;
        tr[x].init(p,v);
    } 
    splay(x,0);
} 
void find(int v){
    int x=root;
    while(tr[x].s[v>tr[x].v]&&v!=tr[x].v)
        x=tr[x].s[v>tr[x].v];
    splay(x,0);
} 
int get_pre(int v){//返回v前驱编号 
    find(v);
    int x=root;
    if(tr[x].v<v) return x;
    x=tr[x].s[0];
    while(tr[x].s[1]) x=tr[x].s[1];
    splay(x,0);
    return x;
}
int get_suc(int v){//后继 
    find(v);
    int x=root;
    if(tr[x].v>v) return x;
    x=tr[x].s[1];
    while(tr[x].s[0]) x=tr[x].s[0];
    splay(x,0);
    return x;
}
void del(int v){//删除 
    int pre=get_pre(v);
    int suc=get_suc(v);
    splay(pre,0),splay(suc,pre);
    int del=tr[suc].s[0];
    if(tr[del].cnt>1)
        tr[del].cnt--,splay(del,0);
    else
        tr[suc].s[0]=0,splay(suc,0);
}
int get_rank(int v){//查询排名 
    insert(v);
    int res=tr[tr[root].s[0]].size;
    del(v);
    return res;
}
int get_val(int k){
    int x=root;
    while(1){
        int y=tr[x].s[0];
        if(tr[y].size+tr[x].cnt<k){
            k-=tr[y].size+tr[x].cnt;
            x=tr[x].s[1];
        }
        else if(tr[y].size>=k) x=y;
        else break;
    }
    splay(x,0);
    return tr[x].v;
}
int main()
{
insert(-0x3f),insert(0x3f);
int n,m,op,a,last=0,ans=0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
    scanf("%d",&a);
    insert(a);
}
while(m){
    scanf("%d%d",&op,&a);
    a^=last;
    if(op==1) insert(a);
    else if(op==2) del(a);
    else if(op==3) 
        last=get_rank(a),ans^=last;
    else if(op==4)
        last=get_val(a+1),ans^=last;
    else if(op==5)
        last=tr[get_pre(a)].v,ans^=last;
    else last=tr[get_suc(a)].v,ans^=last;
    m--;
}   
printf("%d",ans);
   return 0;
}

by caoqcTH68127 @ 2024-09-28 20:34:15

啊,头疼。

代码非常的···


by BHH985211 @ 2024-09-28 20:39:37

@caoqcTH68127 知道啦,把插入的两个哨兵-0x3f,0x3f改成(1<<30)+1,就行了,哨兵不够大


by caoqcTH68127 @ 2024-09-29 18:59:16

@BHH985211 ......(你知道你问我干什么)


by BHH985211 @ 2024-09-29 19:45:42

@caoqcTH68127 发了之后才发现


|