关于评测机返回结果的疑问

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

AmiyaCast @ 2024-08-12 10:01:31

maxn依次改成了1e5(除了#1全MLE),1e6(两个MLE) 2e6(AC),得到的MLE越来越少,为啥呢

#include <algorithm>
#include <cstdio>
#include <iostream>

#define maxn 2000005
#define INF (1 << 30)

int n, m;

struct treap {  // 直接维护成数据结构,可以直接用
    int l[maxn], r[maxn], val[maxn], rnd[maxn], size_[maxn], w[maxn];
    int sz, ans, rt;

    void pushup(int x) {
        size_[x] = size_[l[x]] + size_[r[x]] + w[x];
    }

    void lrotate(int &k) {//左旋
        int t = r[k];
        r[k] = l[t];
        l[t] = k;
        size_[t] = size_[k];
        pushup(k);
        k = t;
    }

    void rrotate(int &k) {//右旋
        int t = l[k];
        l[k] = r[t];
        r[t] = k;
        size_[t] = size_[k];
        pushup(k);
        k = t;
    }

    void insert(int &k, int x) {  // 插入
        if (!k) {
            sz++;
            k = sz;
            size_[k] = 1;
            w[k] = 1;
            val[k] = x;
            rnd[k] = rand();
            return;
        }
        size_[k]++;
        if (val[k] == x) {
            w[k]++;
        } else if (val[k] < x) {
            insert(r[k], x);
            if (rnd[r[k]] < rnd[k]) lrotate(k);
        } else {
            insert(l[k], x);
            if (rnd[l[k]] < rnd[k]) rrotate(k);
        }
    }

    bool del(int &k, int x) {  // 删除节点
        if (!k) return false;
        if (val[k] == x) {
            if (w[k] > 1) {
                w[k]--;
                size_[k]--;
                return true;
            }
            if (l[k] == 0 || r[k] == 0) {
                k = l[k] + r[k];
                return true;
            } else if (rnd[l[k]] < rnd[r[k]]) {
                rrotate(k);
                return del(k, x);
            } else {
                lrotate(k);
                return del(k, x);
            }
        } else if (val[k] < x) {
            bool succ = del(r[k], x);
            if (succ) size_[k]--;
            return succ;
        } else {
            bool succ = del(l[k], x);
            if (succ) size_[k]--;
            return succ;
        }
    }

    int queryrank(int k, int x) {//查询有多少个比自己小的数
        if (!k) return 0;
        if (val[k] == x)
            return size_[l[k]];
        else if (x > val[k]) {
            return size_[l[k]] + w[k] + queryrank(r[k], x);
        } else
            return queryrank(l[k], x);
    }

    int querynum(int k, int x) {//子树k中排名是x的数
        if (!k) return 0;
        if (x <= size_[l[k]])
            return querynum(l[k], x);
        else if (x > size_[l[k]] + w[k])
            return querynum(r[k], x - size_[l[k]] - w[k]);
        else
            return val[k];
    }

    void querypre(int k, int x) {//用ans返回节点编号
        if (!k) return;
        if (val[k] < x)
            ans = k, querypre(r[k], x);
        else
            querypre(l[k], x);
    }

    void querysub(int k, int x) {//用ans返回节点编号
        if (!k) return;
        if (val[k] > x)
            ans = k, querysub(l[k], x);
        else
            querysub(r[k], x);
    }
} T;

int main() {
    srand(123);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i){
        int x; scanf("%d", &x);
        T.insert(T.rt, x);
    }
    int opt, x, last = 0, ans = 0;
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &opt, &x);
        x ^= last;
        if (opt == 1)
            T.insert(T.rt, x);//插入x
        else if (opt == 2)
            T.del(T.rt, x);//删除一个x
        else if (opt == 3) {
            ans ^= (last = T.queryrank(T.rt, x) + 1);//查询x的排名多少个比x小的数 + 1
        } else if (opt == 4) {
            ans ^= (last = T.querynum(T.rt, x));//查询排名是x的数 x是0则返回0
        } else if (opt == 5) {
            T.ans = 0;
            T.querypre(T.rt, x);
            ans ^= (last = T.val[T.ans]);//查询x的前去
        } else if (opt == 6) {
            T.ans = 0;
            T.querysub(T.rt, x);
            ans ^= (last = T.val[T.ans]);//查询x的后记
        }
    }
    printf("%d\n", ans);
    return 0;
}

by eEfiuys @ 2024-08-12 10:04:31

@AmiyaCast 数组开小,访问越界,可能导致任何结果


by AmiyaCast @ 2024-08-12 11:01:19

@aqx_AK_xyf 感谢dalao指点!


|