众所周知有很多种方法能 AC 这道题,于是我们先用普通 Treap 来做一下:
#include <iostream>
#include <random>
using namespace std;
const int N = 5;
int a, b, rt, cnt;
mt19937 rng(random_device{}());
struct node {
int l, r, val, sum, cnt, siz;
mt19937::result_type key;
} tree[N];
void maintain(int rt) {
tree[rt].siz = tree[tree[rt].l].siz + tree[tree[rt].r].siz + tree[rt].cnt;
tree[rt].sum = tree[tree[rt].l].sum + tree[tree[rt].r].sum + tree[rt].cnt * tree[rt].val;
}
pair<int, int> split(int rt, int k) {
if (!rt) return {};
if (tree[rt].val >= k) {
auto [l, r] = split(tree[rt].l, k);
tree[rt].l = r;
maintain(rt);
return {l, rt};
} else {
auto [l, r] = split(tree[rt].r, k);
tree[rt].r = l;
maintain(rt);
return {rt, r};
}
}
int merge(int lt, int rt) {
if (!lt || !rt) return lt + rt;
if (tree[lt].key < tree[rt].key) {
tree[lt].r = merge(tree[lt].r, rt);
maintain(lt);
return lt;
} else {
tree[rt].l = merge(lt, tree[rt].l);
maintain(rt);
return rt;
}
}
void insert(int k) {
auto [l, p] = split(rt, k);
auto [m, r] = split(p, k + 1);
if (m) tree[m].sum += k, ++tree[m].cnt, ++tree[m].siz;
else tree[m = ++cnt] = {0, 0, k, k, 1, 1, rng()};
rt = merge(merge(l, m), r);
}
int query(int x, int y) {
auto [l, p] = split(rt, x);
auto [m, r] = split(p, y + 1);
int res = tree[m].sum;
rt = merge(merge(l, m), r);
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> a >> b;
insert(a);
insert(b);
cout << query(-1e9, 1e9);
return 0;
}
但是用这种普通 Treap 还是太没意思了啊。
于是我们就想到可以把 split
作为减法,merge
作为加法。
这样我们就写出了一棵值域 Treap!(bushi
#include <iostream>
#include <random>
using namespace std;
int a, b;
mt19937 rng(random_device{}());
int lson(int rt) { return (rt - 1) >> 1; }
int rson(int rt) { return (rt - 1) - ((rt - 1) >> 1); }
int maintain(int ls, int rs) { return ls + rs + 1; }
pair<int, int> split(int rt, int x) {
if (!rt) return {};
int ls = lson(rt), rs = rson(rt);
if (ls >= x) {
auto [l, r] = split(ls, x);
return {l, maintain(r, rs)};
} else {
auto [l, r] = split(rs, x - ls - 1);
return {maintain(ls, l), r};
}
}
int merge(int lt, int rt) {
if (!lt || !rt) return lt + rt;
if (rng() & 1) {
int ls = lson(lt), rs = rson(lt);
return maintain(ls, merge(rs, rt));
} else {
int ls = lson(rt), rs = rson(rt);
return maintain(merge(lt, ls), rs);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> a >> b;
if (a >= 0 && b >= 0) cout << merge(a, b);
else if (a >= 0 && b < 0) {
if (a >= -b) cout << split(a, -b).second;
else cout << -split(-b, a).second;
} else if (a < 0 && b >= 0) {
if (b >= -a) cout << split(b, -a).second;
else cout << -split(-a, b).second;
} else cout << -merge(-a, -b);
return 0;
}