如何不MLE
查看原帖
如何不MLE
1198462
dvsfanjo楼主2024/10/7 16:12
#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 的,怎么优化?(如果看到有错也说说)

玄关

2024/10/7 16:12
加载中...