社区讨论
这个为什么多次提交得分不一样
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 条回复,欢迎继续交流。
正在加载回复...