FHQ-Treap 样例过了全 WA 可能是什么原因

P3391 【模板】文艺平衡树

5t0_0r2 @ 2024-07-28 10:12:02

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
int n,m;
struct node{
    int val,pri;
    int lc,rc;
    int siz;
    int tag;
} t[N];
int node_cnt,root;

void push_up(int u){
    t[u].siz = t[t[u].lc].siz + t[t[u].rc].siz + 1;
}

void make_tag(int u){
    t[u].tag ^= 1;
    swap(t[u].lc,t[u].rc);
} 
void push_down(int u){
    if(t[u].tag){
        make_tag(t[u].lc);
        make_tag(t[u].rc);
        t[u].tag = 0;
    }
}

void split(int u,int x,int &L,int &R){//将以u为根的子树分裂成以L,R为根的两棵子树满足左子树所大小为x,
    if(u == 0){
        L = R = 0;
        return;
    }
    push_down(u);
    if(t[t[u].lc].siz <= x){
        L = u;
        split(t[u].rc,x,t[u].rc,R);
    }
    else{
        R = u;
        split(t[u].lc,x,L,t[u].lc);
    }
    push_up(u);
}
/*合并的前提条件:
    1. 保证 t[u].val <= t[v].val
    2. 一个子树中的最大值小于另一个子树中的最小值
*/
int merge(int u,int v){//将以u为根的树和以v为根的子树合并并返回合并后的根 
    if(!u || !v)//如果其中一个根为空那么合并后的根就是另一个根 
        return u | v;
    push_down(u);
    push_down(v);
    if(t[u].pri > t[v].pri){//u优先级大于v优先级,则u应为v的父亲(大根堆性质) 
        t[u].rc = merge(t[u].rc,v);//t[t[u].lc].val <= t[u].val <= t[v].val,所以合并t[u].rc和v
        push_up(u);
        return u;
    }
    else{//否则v应为u的父亲 
        t[v].lc = merge(u,t[v].lc);//t[t[v].rc].val >= t[v].val >= t[u].val,所以合并u和t[v].lc 
        push_up(v);
        return v;
    }
}

void new_node(int x){
    t[++node_cnt] = (node){x,rand() * rand(),0,0,1,0};
}

void reverse(int l,int r){
    int u,v,w;
    split(root,r,u,w);
    split(u,l - 1,u,v);
    make_tag(v);
    root = merge(merge(u,v),w);
}

void print(int u){
    if(!u)
        return;
    push_down(u);
    print(t[u].lc);
    cout << u << ' ';
    print(t[u].rc);
}

int main(){
    srand(time(0));
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin >> n >> m;
    for(int i = 1;i <= n;i++){
        new_node(i);
        root = merge(root,node_cnt);
    }
    while(m--){
        int l,r;
        cin >> l >> r;
        reverse(l,r);
    }
    print(root);
    return 0;
}

by goxjanskloon @ 2024-07-28 11:02:02

@5t0_0r2 能过样例说明你rp高(

rand()须在每次调用前重设随机种子才随机。建议使用std::mt19937(在<random>里):

int rank=std::mt19937(std::random_device().operator()())();

其他没细看


by goxjanskloon @ 2024-07-28 11:04:43

(貌似结果总是随机的


|