关于 Treap

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

Warriors_Cat @ 2020-03-25 20:23:19

请问一下,这道题以下代码为什么 TLE 70 分?

Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
const int INF = 0x7fffffff;
int anss, lst, m, n, opt, x, num, Root, ch[1100010][2], cnt[1100010], siz[1100010], pri[1100010], val[1100010];
inline int new_node(int x){
    val[++num] = x;
    pri[num] = rand();
    cnt[num] = siz[num] = 1;
    return num;
}
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x << 3) + (x << 1) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
inline void upd(int x){
    siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
    return;
}
inline void Rotate(int &x, int id){
    int y = ch[x][id ^ 1];
    ch[x][id ^ 1] = ch[y][id];
    ch[y][id] = x;
    x = y;
    upd(ch[x][id]); upd(x);
    return;
}
inline void Insert(int &x, int key){
    if(!x){
        x = new_node(key);
        return;
    }
    if(key == val[x]) cnt[x]++;
    else{
        int id = key < val[x] ? 0 : 1;
        Insert(ch[x][id], key);
        if(pri[x] < pri[ch[x][id]]) Rotate(x, id ^ 1);
    }
    upd(x);
    return;
}
inline void Delete(int &x, int key){
    if(!x) return;
    if(key == val[x]){
        if(cnt[x] > 1){
            cnt[x]--;
            upd(x);
            return;
        }
        if(ch[x][0] || ch[x][1]){
            if(!ch[x][1] && pri[ch[x][0]] > pri[ch[x][1]]){
                Rotate(x, 1);
                Delete(ch[x][1], key);
            }
            else{
                Rotate(x, 0);
                Delete(ch[x][0], key);
            }
            upd(x);
        }
        else x = 0;
        return;
    }
    if(key < val[x]) Delete(ch[x][0], key);
    else Delete(ch[x][1], key);
    upd(x);
    return;
}
inline int Pre(int key){
    int x = Root, ans = -INF;
    while(x){
        if(val[x] < key) ans = val[x], x = ch[x][1];
        else x = ch[x][0];
    }
    return ans;
}
inline int Suf(int key){
    int x = Root, ans = INF;
    while(x){
        if(val[x] > key) ans = val[x], x = ch[x][0];
        else x = ch[x][1];
    }
    return ans;
}
inline int Find(int x, int key){
    if(!x) return 0;
    if(key == val[x]) return siz[ch[x][0]] + 1;
    else if(key < val[x]) return Find(ch[x][0], key);
    else return siz[ch[x][0]] + cnt[x] + Find(ch[x][1], key);
}
inline int Rank(int x, int k){
    if(!x) return INF;
    if(k <= siz[ch[x][0]]) return Rank(ch[x][0], k);
    else if(k <= siz[ch[x][0]] + cnt[x]) return val[x];
    else return Rank(ch[x][1], k - siz[ch[x][0]] - cnt[x]);
}
int main(){
    Root = new_node(-INF), ch[Root][1] = new_node(INF);
    upd(Root);
    n = read(); m = read();
    for(register int i = 1; i <= n; ++i){
        x = read();
        Insert(Root, x);
    }
    for(register int i = 1; i <= m; ++i){
        opt = read(); x = read();
        x ^= lst;
        if(opt == 1) Insert(Root, x);
        if(opt == 2) Delete(Root, x);
        if(opt == 3) Insert(Root, x), lst = Find(Root, x) - 1, anss ^= lst, Delete(Root, x);
        if(opt == 4) lst = Rank(Root, x + 1), anss ^= lst;
        if(opt == 5) Insert(Root, x), lst = Pre(x), anss ^= lst, Delete(Root, x);
        if(opt == 6) Insert(Root, x), lst = Suf(x), anss ^= lst, Delete(Root, x);
    }
    printf("%d", anss);
    return 0;
}

自认为常数已经够优了,或者说是我的写法有问题?


by IntrepidStrayer @ 2020-03-25 20:25:28

@蒟蒻的名字 明显有问题,一次操作:插入-查询-删除 这是什么操作


by Smile_Cindy @ 2020-03-25 20:25:42

@蒟蒻的名字 rank,pre,suf实现的精细一点可以不用插入删除。

鉴于是Splay写的,代码就不发了。


by Smile_Cindy @ 2020-03-25 20:26:00

@fhh_orz 这么做主要是为了保证正确性的。


by Warriors_Cat @ 2020-03-25 20:26:03

@fhh_orz 很正常啊,又没说这个数在序列里一定有


by IntrepidStrayer @ 2020-03-25 20:27:22

本题强制在线,保证所有操作合法(操作 22 保证存在至少一个 xx,操作 4,5,64,5,6 保证存在答案)。

456肯定有答案,3的话找不到返回1即可


by Smile_Cindy @ 2020-03-25 20:28:47

@fhh_orz 是有答案,但是有的人的代码实现得不够精细所以需要插入删除。


by IntrepidStrayer @ 2020-03-25 20:29:06

@蒟蒻的名字 4保证有答案,56完全不需要它在树内,3的话找不到返回1就行了


by Smile_Cindy @ 2020-03-25 20:29:13

@fhh_orz 只是保证有答案,没保证数x一定在序列中出现过。


by IntrepidStrayer @ 2020-03-25 20:29:32

@Alpha 嗯,知道了


by Warriors_Cat @ 2020-03-25 20:29:32

@fhh_orz 不是有答案无答案的问题,是这个序列里有可能根本没有 x 这个数


| 下一页