#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 5e4 + 5;
ll n, m, op, l, r, k, a[maxn];
struct FHQ_Treap {
ll sz[maxn], l[maxn], r[maxn], val[maxn], key[maxn];
ll root, idx;
void ini() {
root = idx = 0;
return;
}
ll New(ll v) {
idx++;
sz[idx] = 1;
val[idx] = v;
key[idx] = rand();
return idx;
}
void Pushup(ll u) {
sz[u] = sz[l[u]] + sz[r[u]] + 1;
return;
}
void Split(ll u, ll v, ll &x, ll &y) {
if (!u) {
x = y = 0;
return;
}
if (val[u] <= v) {
x = u;
Split(r[u], v, r[u], y);
} else {
y = u;
Split(l[u], v, x, l[u]);
}
Pushup(u);
return;
}
ll Merge(ll x, ll y) {
if (!x || !y)
return x | y;
if (key[x] < key[y]) {
r[x] = Merge(r[x], y);
Pushup(x);
return x;
} else {
l[y] = Merge(x, l[y]);
Pushup(y);
return y;
}
}
void Insert(ll v) {
ll x, y;
Split(root, v, x, y);
root = Merge(Merge(x, New(v)), y);
return;
}
void Delete(ll v) {
ll x, y, z;
Split(root, v, x, y);
Split(x, v - 1, x, z);
z = Merge(l[z], r[z]);
root = Merge(Merge(x, z), y);
return;
}
ll Rank(ll v) {
ll x, y, z;
Split(root, v - 1, x, y);
z = sz[x] + 1;
root = Merge(x, y);
return z;
}
ll K_th(ll u, ll k) {
if (!u)
return 1;
if (sz[l[u]] + 1 == k)
return val[u];
if (sz[l[u]] >= k)
return K_th(l[u], k);
return K_th(r[u], k - sz[l[u]] - 1);
}
ll Pre(ll v) {
if (K_th(root, 1) > v)
return -2147483647;
ll x, y, z;
Split(root, v - 1, x, y);
z = K_th(x, sz[x]);
root = Merge(x, y);
return val[z];
}
ll Suc(ll v) {
if (K_th(root, sz[root]) < v)
return 2147483647;
ll x, y, z;
Split(root, v, x, y);
z = K_th(y, 1);
root = Merge(x, y);
return val[z];
}
};
struct SegTree {
FHQ_Treap t[maxn << 2];
void build(ll l, ll r, ll i) {
t[i].ini();
for (int i = l; i <= r; i++)
t[i].Insert(a[i]);
if (l == r)
return;
ll mid = (l + r) >> 1;
build(l, mid, i << 1);
build(mid + 1, r, i << 1 | 1);
return;
}
void update(ll l, ll r, ll i, ll w, ll k) {
t[i].Delete(a[w]);
t[i].Insert(k);
if (l == r && l == w) {
a[w] = k;
return;
}
ll mid = (l + r) >> 1;
if (w <= mid)
update(l, mid, i << 1, w, k);
else
update(mid + 1, r, i << 1 | 1, w, k);
return;
}
ll rank(ll l, ll r, ll i, ll a, ll b, ll k) {
if (a <= l && r <= b)
return t[i].Rank(k);
ll mid = (l + r) >> 1, ans = 0;
if (a <= mid)
ans += rank(l, mid, i << 1, a, b, k);
if (mid < b)
ans += rank(mid + 1, r, i << 1 | 1, a, b, k);
return ans;
}
ll k_th(ll l, ll r, ll k) {
ll x = 0, y = 1e9;
while (x < y) {
ll mid = (x + y + 1) >> 1;
if (rank(1, n, 1, l, r, mid) < k)
l = mid;
else
r = mid - 1;
}
return r;
}
ll pre(ll l, ll r, ll i, ll a, ll b, ll k) {
if (a <= l && r <= b)
return t[i].Pre(k);
ll mid = (l + r) >> 1, ans = -1e18;
if (a <= mid)
ans = max(ans, pre(l, mid, i << 1, a, b, k));
if (mid < b)
ans = max(ans, pre(mid + 1, r, i << 1 | 1, a, b, k));
return ans;
}
ll suc(ll l, ll r, ll i, ll a, ll b, ll k) {
if (a <= l && r <= b)
return t[i].Suc(k);
ll mid = (l + r) >> 1, ans = 1e18;
if (a <= mid)
ans = min(ans, suc(l, mid, i << 1, a, b, k));
if (mid < b)
ans = min(ans, suc(mid + 1, r, i << 1 | 1, a, b, k));
return ans;
}
} tree;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
tree.build(1, n, 1);
while (m--) {
cin >> op >> l >> r;
if (op != 3)
cin >> k;
if (op == 1)
cout << tree.rank(1, n, 1, l, r, k) << '\n';
else if (op == 2)
cout << tree.k_th(l, r, k) << '\n';
else if (op == 3)
tree.update(1, n, 1, l, r);
else if (op == 4)
tree.pre(1, n, 1, l, r, k);
else if (op == 5)
tree.suc(1, n, 1, l, r, k);
}
return 0;
}
这段代码是明显 MLE 的,怎么优化?(如果看到有错也说说)
玄关