splay 求卡常 88分 马峰良好

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

simonG @ 2023-01-13 09:42:45

#include<bits/stdc++.h>
using namespace std;
const int N=11e5+10;
int n,m,last,ans;
int rt,tot;
int fa[N],ch[N][2],val[N],cnt[N],sz[N];
bool get(int x) {return ch[fa[x]][1]==x;}
void pushup(int x) {
    if(x) {
        sz[x]=cnt[x];
        if(ch[x][0]) sz[x]+=sz[ch[x][0]];
        if(ch[x][1]) sz[x]+=sz[ch[x][1]];
    }
}
void rotate(int x) {
    int y=fa[x],z=fa[y],k=get(x);
    ch[y][k]=ch[x][k^1]; fa[ch[x][k^1]]=y;
    ch[x][k^1]=y; fa[y]=x;
    fa[x]=z;
    if(z) ch[z][ch[z][1]==y]=x;
    pushup(y); pushup(x);
}
void splay(int x,int goal=0) {
    for(; fa[x]!=goal; ) {
        int y=fa[x],z=fa[y];
        if(z!=goal) rotate(get(x)==get(y)?y:x);
        rotate(x);
    }
    if(goal==0) rt=x;
}
void find(int x) {
    int u=rt;
    if(!u) return ;
    for(; ch[u][x>val[u]]&&x!=val[u]; )
        u=ch[u][x>val[u]];
    splay(u,0);
}
void insert(int x) {
    int u=rt,f=0;
    for(; u&&val[u]!=x; ) {
        f=u;
        u=ch[u][x>val[u]];
    }
    if(u) {cnt[u]++; pushup(u); pushup(f);}
    else {
        u=++tot;
        val[u]=x; sz[u]=cnt[u]=1;
        fa[u]=f; ch[u][0]=ch[u][1]=0;
        if(f) {ch[f][x>val[f]]=u; pushup(f);}
        else rt=u;
    }
    splay(u,0);
}
int query_rank(int x) {
    find(x);
    if(val[rt]>=x) return sz[ch[rt][0]]+1;
    else return sz[ch[rt][0]]+cnt[rt]+1;
}
int query_kth(int x) {
    int u=rt;
    for(; ; ) {
        if(ch[u][0]&&x<=sz[ch[u][0]])
            u=ch[u][0];
        else {
            int tmp=sz[ch[u][0]]+cnt[u];
            if(x<=tmp) return val[u];
            x-=tmp; u=ch[u][1]; 
        }
    }
}
int pre(int x) {
    find(x);
    if(val[rt]<x) return rt;
    int u=ch[rt][0];
    for(; ch[u][1]; ) u=ch[u][1];
    return u;
}
int succ(int x) {
    find(x);
    if(val[rt]>x) return rt;
    int u=ch[rt][1];
    for(; ch[u][0]; ) u=ch[u][0];
    return u;
}
void del(int x) {
    find(x);
    if(cnt[rt]>1) {cnt[rt]--; pushup(rt); return ;}
    if(!ch[rt][0]&&!ch[rt][1]) {rt=0; return ;}
    if(!ch[rt][0]||!ch[rt][1]) {
        rt=ch[rt][0]?ch[rt][0]:ch[rt][1];
        fa[rt]=0;
        return ;
    }
    int ort=rt,p=pre(x);
    splay(p);
    ch[rt][1]=ch[ort][1]; fa[ch[ort][1]]=rt;
    pushup(rt);
}
int main() {
    scanf("%d%d",&n,&m);
    for(int x; n--; ) {
        scanf("%d",&x);
        insert(x);
    }
    for(int op,x; m--; ) {
        scanf("%d%d",&op,&x);
        x^=last;
        switch(op) {
            case 1: insert(x); break;
            case 2: del(x); break;
            case 3: last=query_rank(x); ans^=last; break;
            case 4: last=query_kth(x); ans^=last; break;
            case 5: last=val[pre(x)]; ans^=last; break;
            case 6: last=val[succ(x)]; ans^=last; break;
        }
    }
    printf("%d\n",ans);
    return 0;
}

by reveal @ 2023-01-13 10:22:25

考虑将结点信息打包进类里,拆分为多个数组对内存不友好


by simonG @ 2023-01-13 10:43:01

谢谢,在 query_kth,pre,succ 后加 splay(u,0) 即过了


|