社区讨论

这个为什么多次提交得分不一样

P3380【模板】树套树参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mjin30bz
此快照首次捕获于
2025/12/23 21:47
3 个月前
此快照最后确认于
2025/12/26 17:35
2 个月前
查看原帖
CPP
#include<bits/stdc++.h>
using std::cin, std::cout, std::random_device, std::mt19937, std::max, std::min;
const int N = 5e4+1;
int n, m, opt, l, r, pos, k, a[N];
random_device rd;
mt19937 mt(rd());
struct Node{
    int val, cnt, sz, pri;
    Node *l, *r;
    Node():val(0),sz(1),cnt(1),l(nullptr),r(nullptr){pri = mt();}
    Node(int val):val(val),sz(1),cnt(1),l(nullptr),r(nullptr){pri = mt();}
    inline void pushup(){sz=cnt;if(l)sz+=l->sz;if(r)sz+=r->sz;}
}* treap[4*N];
void split(Node* p, int val, Node*&u, Node*&v){
    // {<=val, >val}
    if (!p) {u = v = nullptr; return;}
    Node*l, *r;
    if (val < p->val){
        split(p->l, val, l, r);
        p->l = r;
        p->pushup();
        u = l;
        v = p;
    } else {
        split(p->r, val, l, r);
        p->r = l;
        p->pushup();
        u = p;
        v = r;
    }
}
void split1(Node* p, int rk, Node*&l, Node*&mid, Node*&r){
    // {<=rk, >rk}
    if (!p) {l = mid = r = nullptr; return;}
    int less = p->l ? p->l->sz : 0;
    if (rk <= less){
        split1(p->l, rk, l, mid, p->l);
        p->pushup();
        r = p;
    } else if (rk <= less + p->cnt){
        l = p->l;
        r = p->r;
        p->l = p->r = nullptr;
        p->pushup();
        mid = p;
    } else {
        split1(p->r, rk-less-p->cnt, p->r, mid, r);
        p->pushup();
        l = p;
    }
}
Node* merge(Node* p, Node* q){
    if (!p) return q;
    if (!q) return p;
    if (p->pri <= q->pri){
        p->r = merge(p->r, q);
        p->pushup();
        return p;
    } else {
        q->l = merge(p, q->l);
        q->pushup();
        return q;
    }
}
void insert(Node*&p, int u){
    Node *l, *mid, *r;
    split(p, u, l, r);
    split(l, u-1, l, mid);
    if (!mid) mid = new Node(u);
    else ++mid->cnt;
    p = merge(merge(l, mid), r);
}
void del(Node*&p, int u){
    Node *l, *mid, *r;
    split(p, u, l, r);
    split(l, u-1, l, mid);
    if (mid){
        if (mid->cnt==1){
            delete mid;
            mid = nullptr;
        } else --mid->cnt;
    }
    p = merge(merge(l, mid), r);
}
int rank(Node*&p, int k){
    Node *l, *r;
    split(p, k-1, l, r);
    int ans = l ? l->sz+1 : 1;
    p = merge(l, r);
    return ans;
}
int getval(Node*&p, int rk){
    Node *l, *mid, *r;
    split1(p, rk, l, mid, r);
    int ans = mid -> val;
    p = merge(merge(l, mid), r);
    return ans;
}
int prev(Node*&p, int x){
    Node *l, *r, *u;
    split(p, x-1, l, r);
    int ans = -2147483647;
    u = l;
    while(u){
        ans = u->val;
        u = u->r;
    }
    p = merge(l, r);
    return ans;
}
int next(Node*&p, int x){
    Node *l, *r, *u;
    split(p, x, l, r);
    int ans = 2147483647;
    u = r;
    while(u){
        ans = u->val;
        u = u->l;
    }
    p = merge(l, r);
    return ans;
}
void build(int p, int l, int r){
    for(int i=l;i<=r;++i) insert(treap[p], a[i]);//, cout<<p<<' '<<l<<' '<<r<<' '<<i<<' '<<a[i]<<'\n';
    if (l==r) return;
    int mid = l + r >> 1;
    build(p*2, l, mid);
    build(p*2+1, mid+1, r);
}
void modify(int p, int l, int r, int s, int t){
    del(treap[p], a[s]);
    insert(treap[p], t);
    //cout<<p<<' '<<l<<' '<<r<<' '<<s<<' '<<t<<'\n';
    if (l==r) return;
    int mid = l + r >> 1;
    if (s<=mid) modify(p*2, l, mid, s, t);
    else modify(p*2+1, mid+1, r, s, t);
}
int rank(int p, int l, int r, int s, int t, int k){
    if (s <= l && r <= t) return rank(treap[p], k);
    int mid = l + r >> 1, ans = 0;
    if (s <= mid) ans = rank(p*2, l, mid, s, t, k) - 1;
    if (t > mid) ans += rank(p*2+1, mid+1, r, s, t, k) - 1;
    return ++ans;
}
int prev(int p, int l, int r, int s, int t, int k){
    if (s <= l && r <= t) return prev(treap[p], k);
    int mid = l + r >> 1, ans = -2147483647;
    if (s <= mid) ans = prev(p*2, l, mid, s, t, k);
    if (t > mid) ans = max(ans, prev(p*2+1, mid+1, r, s, t, k));
    return ans;
}
int next(int p, int l, int r, int s, int t, int k){
    if (s <= l && r <= t) return next(treap[p], k);
    int mid = l + r >> 1, ans = 2147483647;
    if (s <= mid) ans = next(p*2, l, mid, s, t, k);
    if (t > mid) ans = min(ans, next(p*2+1, mid+1, r, s, t, k));
    return ans;
}
int getval(int p, int l, int r, int s, int t, int k){
    int L = -2147483647, R = 2147483647;
    while(L<R){
        int mid = (long long)L + R + 1 >> 1;
        //cout<<L<<' '<<R<<' '<<mid<<' '<<rank(p, l, r, s, t, mid)<<'\n';
        if (rank(p, l, r, s, t, mid) > k) R = mid - 1;
        else L = mid;
    }
    return L;
}
void print(Node *p){
    if (!p) return;
    print(p->l);
    cout << p->val << ' ';
    print(p->r);
}
void check(int p, int l, int r){
    cout << p << ' ' << l << ' ' << r << ": ";
    print(treap[p]);
    cout << '\n';
    if (l==r) return;
    int mid = l + r >> 1;
    check(p*2, l, mid);
    check(p*2+1, mid+1, r);
}

int main(){
    memset(treap, 0, sizeof treap);
    cin>>n>>m;
    for(int i=1;i<=n;++i) cin>>a[i];
    build(1, 1, n);
    while(m--){
        cin>>opt;
        if (opt==1){
            cin>>l>>r>>k;
            cout << rank(1, 1, n, l, r, k) << '\n';
        } else if (opt==2){
            cin>>l>>r>>k;
            cout << getval(1, 1, n, l, r, k) << '\n';
        } else if (opt==3){
            cin>>pos>>k;
            modify(1, 1, n, pos, k);
            a[pos] = k;
        } else if (opt==4){
            cin>>l>>r>>k;
            cout << prev(1, 1, n, l, r, k) << '\n';
        } else {
            cin>>l>>r>>k;
            cout << next(1, 1, n, l, r, k) << '\n';
        }
        //for(int i=1;i<=n;++i) cout<<a[i]<<' ';cout<<'\n';
        //check(1, 1, n);cout<<'\n';
    }
}

回复

1 条回复,欢迎继续交流。

正在加载回复...