Rt,我在 Treap 中用了 vector,在插入函数中因为是 vector 所以无法使用引用传递参数(也就是使用 ll &x)来修改 x 的值,所以改成了让插入函数返回 x 修改后的值。
结果如果使用 a[x].l = insrt(a[x].l, k); 直接修改 a[x].l 的值会导致 a[x].l 没有被修改,连样例都过不去;如果加一个变量进行过渡(比如 ll q = insrt(a[x].l, k); a[x].l = q;)就可以成功修改 a[x].l,并 AC。
请各位巨佬帮忙解答一下这个玄学错误是因为什么?
无法过样例的代码中的插入函数:
ll insrt(ll x, abc k) {
ll p = x;
if (x == 0) {
p = new_nde(k);
return p;
}
if (k < a[x].val || k == a[x].val) {
a[x].l = insrt(a[x].l, k);
// ll q = insrt(a[x].l, k);
// a[x].l = q;
pushup(x);
if (a[x].rnd < a[a[x].l].rnd) {
p = rrtt(x);
}
}
else {
a[x].r = insrt(a[x].r, k);
// ll q = insrt(a[x].r, k);
// a[x].r = q;
pushup(x);
if (a[x].rnd < a[a[x].r].rnd) {
p = lrtt(x);
}
}
return p;
}
AC 代码中的插入函数:
ll insrt(ll x, abc k) {
ll p = x;
if (x == 0) {
p = new_nde(k);
return p;
}
if (k < a[x].val || k == a[x].val) {
// a[x].l = insrt(a[x].l, k);
ll q = insrt(a[x].l, k);
a[x].l = q;
pushup(x);
if (a[x].rnd < a[a[x].l].rnd) {
p = rrtt(x);
}
}
else {
// a[x].r = insrt(a[x].r, k);
ll q = insrt(a[x].r, k);
a[x].r = q;
pushup(x);
if (a[x].rnd < a[a[x].r].rnd) {
p = lrtt(x);
}
}
return p;
}
下面是完整的 AC 代码:(评测记录)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 100000;
const ll N = maxn + 10;
ll n, m, Q, x, y, res, fa[N];
char ch;
struct abc{
ll x, y; // x is the importance of the node, and y is the id of the node.
bool operator < (abc p) {
return x < p.x;
}
bool operator == (abc p) {
return x == p.x;
}
}a[N];
struct nde{
abc val;
ll rnd, siz, l, r;
};
struct TRP{
ll rt;
vector<nde> a;
void clr() {
rt = 0;
a.clear();
a.push_back((nde){0, 0, 0, 0, 0});
}
ll new_nde(abc k) {
a.push_back((nde){k, rand(), 1, 0, 0});
return (ll)(a.size()) - 1;
}
void pushup(ll x) {
a[x].siz = a[a[x].l].siz + a[a[x].r].siz + 1;
}
ll lrtt(ll x) {
ll p = a[x].r;
a[x].r = a[p].l;
a[p].l = x;
pushup(x);
pushup(p);
return p;
}
ll rrtt(ll x) {
ll p = a[x].l;
a[x].l = a[p].r;
a[p].r = x;
pushup(x);
pushup(p);
return p;
}
ll insrt(ll x, abc k) {
ll p = x;
if (x == 0) {
p = new_nde(k);
return p;
}
if (k < a[x].val || k == a[x].val) {
// a[x].l = insrt(a[x].l, k);
ll q = insrt(a[x].l, k);
a[x].l = q;
pushup(x);
if (a[x].rnd < a[a[x].l].rnd) {
p = rrtt(x);
}
}
else {
// a[x].r = insrt(a[x].r, k);
ll q = insrt(a[x].r, k);
a[x].r = q;
pushup(x);
if (a[x].rnd < a[a[x].r].rnd) {
p = lrtt(x);
}
}
return p;
}
abc get_val(ll x, ll k) {
if (x == 0) {
return (abc){-1, -1};
}
if (k == a[a[x].l].siz + 1) {
return a[x].val;
}
else if (k <= a[a[x].l].siz) {
return get_val(a[x].l, k);
}
else {
return get_val(a[x].r, k - a[a[x].l].siz - 1);
}
}
}g[N];
ll get_fa(ll x) {
if (fa[x] == x) {
return x;
}
else {
fa[x] = get_fa(fa[x]);
return fa[x];
}
}
void mrge(ll x, ll y) {
ll p = get_fa(x), q = get_fa(y);
if (p == q) {
return;
}
if ((ll)(g[p].a.size()) < (ll)(g[q].a.size())) {
swap(p, q);
}
fa[q] = p;
for (ll i = 1; i < (ll)(g[q].a.size()); ++i) {
g[p].rt = g[p].insrt(g[p].rt, g[q].a[i].val);
}
g[q].clr();
}
ll rd() {
char ch = getchar();
ll s = 0, w = 1;
while (ch < '0' || ch > '9') {
if (ch == '-') {
w = -1;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
s = (s << 3) + (s << 1) + (ch ^ 48);
ch = getchar();
}
return (s * w);
}
int main() {
n = rd(); m = rd();
for (ll i = 1; i <= n; ++i) {
a[i].x = rd();
a[i].y = i;
}
for (ll i = 1; i <= n; ++i) {
fa[i] = i;
g[i].clr();
g[i].rt = g[i].insrt(g[i].rt, a[i]);
}
{ll u, v;
for (ll i = 1; i <= m; ++i) {
u = rd(); v = rd();
mrge(u, v);
}}
Q = rd();
for (ll i = 1; i <= Q; ++i) {
cin >> ch;
if (ch == 'Q') {
x = rd(); y = rd();
ll p = get_fa(x);
res = g[p].get_val(g[p].rt, y).y;
printf("%lld\n", res);
}
else {
x = rd(); y = rd();
mrge(x, y);
}
}
return 0;
}
变量名和码风有些奇怪,请巨佬们不要吐槽。