fhq-treap模板44WA,求调

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

XSean @ 2023-06-13 11:47:53

#include <bits/stdc++.h>

#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define pre(i, a, b) for(int i = (a); i >= (b); i--)
#define Ede(i, u) for(int i = h[u]; i; i = ne[i])
#define go(i, a) for(auto i : a)
//#define int long long
#define LL long long
#define ULL unsigned long long
#define PII pair<int, int>
#define PIL pair<int, long long>
#define PLI pair<long long, int>
#define PLL pair<long long, long long>
#define mp make_pair
#define eb emplace_back
#define opb pop_back
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define sf scanf
#define prf printf
#define el putchar('\n')
#define mms(arr, n) memset(arr, n, sizeof(arr))
#define mmc(arr1, arr2) memcpy(arr1, arr2, sizeof(arr2))
#define Db(x) prf("test(%s): ", x)
const int inf = 0x3f3f3f3f;

template <typename T> inline void rd(T &x){
    x = 0; bool f = true; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = false; ch = getchar();}
    while(ch >= '0' && ch <= '9'){ x = (x << 1) + (x << 3) + (ch ^ '0'); ch = getchar();}
    if(!f) x = -x;
}
template <typename T, typename ...Args> inline void rd(T &x, Args &...args){ rd(x); rd(args...);}
#define ls(p) fhq[p].l
#define rs(p) fhq[p].r
#define val(p) fhq[p].val
#define key(p) fhq[p].key
#define siz(p) fhq[p].siz 
using namespace std;

const int N = 1e5 + 10, M = 1e6 + 10;
int n, m;
int a[N];
struct Node{
    int l, r;
    int val, key;
    int siz;
}fhq[N + M];
int root, cnt;
mt19937 ran(time(0));
int newnode(int val){
    val(++cnt) = val;
    key(cnt) = ran();
    siz(cnt) = 1;
    return cnt;
}
void pushup(int p){
    siz(p) = siz(ls(p)) + siz(rs(p)) + 1;
}
void split(int p, int v, int &x, int &y){
    if(!p){ x = y = 0; return;}
    if(val(p) <= v){ x = p; split(rs(p), v, rs(p), y);}
    else{ y = p; split(ls(p), v, x, ls(p));}
    pushup(p);
}
int merge(int x, int y){
    if(!x || !y) return x + y;
    if(key(x) > key(y)){
        rs(x) = merge(rs(x), y);
        pushup(x); return x;
    }else{
        ls(y) = merge(x, ls(y));
        pushup(y); return y;
    }
}
int x, y, z;
void ins(int val){
    split(root, val, x, y);
    root = merge(merge(x, newnode(val)), y);
}
void del(int val){
    split(root, val - 1, x, z);
    split(z, val, y, z);
    y = merge(ls(y), rs(y));
    root = merge(merge(x, y), z);
}
int get_rk(int val){
    split(root, val - 1, x, y);
    int temp = siz(x) + 1;
    root = merge(x, y);
    return temp;
}
int get_val(int k){
    int now = root;
    while(now){
        if(siz(ls(now)) + 1 == k) break;
        else if(k <= siz(ls(now))) now = ls(now);
        else{ now = rs(now); k -= (siz(ls(now)) + 1);}
    }
    return val(now);
}
int get_pre(int val){
    split(root, val - 1, x, y);
    int now = x;
    while(rs(now)) now = rs(now);
    int temp = val(now);
    root = merge(x, y); //其实没有关系 
    return temp;
}
int get_suc(int val){
    split(root, val, x, y);
    int now = y;
    while(ls(now)) now = ls(now);
    int temp = val(now);
    root = merge(x, y);
    return temp;
}
int main(){
    /*
    freopen(".in", "r", stdin);
    freopen(".out", "w", stdout);
    */
    rd(n, m);
    rep(i, 1, n) rd(a[i]), ins(a[i]);
    int ans = 0, last = 0;
    rep(i, 1, m){
        int op, x; rd(op, x); x ^= last;
        if(op == 1) ins(x);
        else if(op == 2) del(x);
        else if(op == 3) last = get_rk(x);
        else if(op == 4) last = get_val(x);
        else if(op == 5) last = get_pre(x);
        else last = get_suc(x);
        if(op >= 3) ans ^= last;
    }
    prf("%d\n", ans);
    return 0;
}

by Terrible @ 2023-06-13 13:26:17

@Sean_xzx

get_valk 的更新次序错了,应该先更新 k 再跳右子树。

else{k -= (siz(ls(now)) + 1);now = rs(now);}

就这一个问题。

另外,警示一句:mt19937 生成的 int 值是有正有负的,这在某些旋转 Treap 程序里是很致命的,建议使用 unsigned int,当然在常见的 fhq_Treap 里不会有这个问题,望知。


by XSean @ 2023-06-13 14:18:22

@Terrible 兄弟,你真的是我的救星啊,救了我两次了,太感谢了


by XSean @ 2023-06-13 14:21:49

@Terrible 太清楚了,每次都可以准确击中我的错误,强


|