在查区间的时候,用一个fhq的类去把区间内所有的fhq都合并在一起,然后再查,这样的做法有没有正确性啊??? 蒟蒻写了好久,测试样例完全过不了。 求大佬调
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF32_MAX 2147483647
#define endl '\n'
void debug(string str)
{
cout << "The " << str << " is OK." << endl;
}
mt19937 rnd(233);
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - 48;
ch = getchar();
}
return x * f;
}
const int N = 1e6;
struct node
{
node *ls, *rs;
int val, rand, size;
explicit node(int x = 0) : size(1)
{
ls = rs = nullptr;
rand = rnd();
val = x;
size = 1;
}
};
class fhq_treap
{
public:
node *root = new node();
node *L = new node(), *R = new node();
node *p = new node();
void push_up(node *u)
{
u->size = (u->ls ? u->ls->size : 0) + (u->rs ? u->rs->size : 0) + 1;
}
void split(node *u, int x, node *&L, node *&R)
{
if (!u)
return L = R = nullptr, void();
int less = (u->ls ? u->ls->size : 0) + 1;
if (x >= less)
{
L = u;
split(u->rs, x - less, u->rs, R);
}
else
{
R = u;
split(u->ls, x, L, u->ls);
}
push_up(u);
}
node *merge(node *L, node *R)
{
if (!L || !R)
return L ? L : R;
if (L->rand > R->rand)
{
L->rs = merge(L->rs, R);
push_up(L);
return L;
}
else
{
R->ls = merge(L, R->ls);
push_up(R);
return R;
}
}
void split_val(node *u, int x, node *&L, node *&R)
{
if (!u)
return L = R = nullptr, void();
if (u->val <= x)
{
L = u;
split_val(u->rs, x, u->rs, R);
}
else
{
R = u;
split_val(u->ls, x, L, u->ls);
}
push_up(u);
}
int get_rank(int val)
{
split(root, val - 1, L, R);
int rank = L->size + 1;
root = merge(L, R);
return rank;
}
int get_val(int rank)
{
node *p = root;
while (p)
{
if ((p->ls ? p->ls->size : 0) + 1 == rank)
break;
else if ((p->ls ? p->ls->size : 0) >= rank && p->ls)
p = p->ls;
else
rank -= (p->ls ? p->ls->size : 0) + 1,
p = p->rs;
}
return p->val;
}
void del(node *u)
{
if (!u)
return;
if (u->ls)
del(u->ls);
if (u->rs)
del(u->rs);
delete u;
}
int get_pre(int val)
{
split(root, val - 1, L, R);
node *p = L;
while (p->rs)
p = p->rs;
val = p->val;
root = merge(L, R);
return val;
}
int get_next(int val)
{
split(root, val, L, R);
node *p = R;
while (p->ls)
p = p->ls;
val = p->val;
root = merge(L, R);
return val;
}
void out(node *u)
{
if (u == nullptr)
return;
if (u->ls)
out(u->ls);
cout << u->val << endl;
if (u->rs)
out(u->rs);
}
~fhq_treap()
{
delete root;
}
};
struct code
{
code *ls, *rs;
fhq_treap fhq;
int l, r;
int val;
explicit code()
{
ls = rs = nullptr;
l = r = 0;
val = 0;
}
};
int a[N];
int n, m;
code *root = new code();
void push_up(code *u)
{
if (u == nullptr)
return;
if (u->ls && u->rs)
u->fhq.root = u->fhq.merge(u->ls->fhq.root, u->rs->fhq.root);
else if (u->ls)
u->fhq.root = u->ls->fhq.root;
else
u->fhq.root = u->rs->fhq.root;
}
void build(code *u, int l, int r)
{
if (u == nullptr)
return;
u->l = l, u->r = r;
if (l == r)
{
u->val = a[l];
u->fhq.root = new node(u->val);
return;
}
int mid = (l + r) >> 1;
u->ls = new code();
u->rs = new code();
build(u->ls, l, mid);
build(u->rs, mid + 1, r);
push_up(u);
}
int get_rank(code *u, int l, int r, int val)
{
if (u == nullptr)
return 0;
int ans = 0;
if (l <= u->l && u->r <= r)
return u->fhq.get_rank(val);
int mid = (l + r) >> 1;
if (l <= mid)
ans += get_rank(u->ls, l, mid, val);
if (r > mid)
ans += get_rank(u->rs, mid + 1, r, val);
return ans;
}
void gets_val(code *u, int l, int r, fhq_treap &vivo50)
{
if (u == nullptr)
return;
if (l <= u->l && u->r <= r)
{
vivo50.root = vivo50.merge(vivo50.root, u->fhq.root);
return;
}
int mid = (l + r) >> 1;
if (l <= mid)
gets_val(u->ls, l, mid, vivo50);
if (r > mid)
gets_val(u->rs, mid + 1, r, vivo50);
}
int get_val(int l, int r, int rank)
{
fhq_treap fhq;
gets_val(root, l, r, fhq);
int res = fhq.get_val(rank);
delete fhq.root;
return res;
}
void modify(code *u, int pos, int val)
{
if (u == nullptr)
return;
if (u->l == u->r && u->l == pos)
{
node *L, *R, *p;
u->fhq.split(u->fhq.root, pos - 1, L, R);
u->fhq.split(u->fhq.root, pos, R, p);
u->fhq.root = u->fhq.merge(L, u->fhq.merge(new node(val), p));
u->val = val;
return;
}
int mid = (u->l + u->r) >> 1;
if (mid >= pos)
modify(u->ls, pos, val);
else
modify(u->rs, pos, val);
push_up(u);
}
void get_all(code *u, int l, int r, fhq_treap &vivo)
{
if (u == nullptr)
return;
if (l <= u->l and u->r <= r)
{
vivo.root = vivo.merge(vivo.root, u->fhq.root);
return;
}
int mid = l + r >> 1;
if (l <= mid)
get_all(u->ls, l, mid, vivo);
if (r > mid)
get_all(u->rs, mid + 1, r, vivo);
}
int get_pre_next(int l, int r, int val, string str)
{
fhq_treap fhq;
get_all(root, l, r, fhq);
if (str == "pre")
{
int pre = fhq.get_pre(val);
return pre;
}
else
{
int ne = fhq.get_next(val);
return ne;
}
}
signed main()
{
n = read();
m = read();
for (int i = 1; i <= n; i++)
a[i] = read();
build(root, 1, n);
for (int i = 1; i <= m; i++)
{
int l, r, k, pos;
int opt = read();
if (opt == 1)
{
l = read(), r = read(), k = read();
int rank = get_rank(root, l, r, k);
cout << rank << endl;
}
else if (opt == 2)
{
l = read(), r = read(), k = read();
int val =
get_val(l, r, k);
cout << val << endl;
}
else if (opt == 3)
{
pos = read(), k = read();
modify(root, pos, k);
}
else if (opt == 4)
{
l = read(), r = read(), k = read();
int pre = get_pre_next(l, r, k, "pre");
cout << pre << endl;
}
else if (opt == 5)
{
l = read(), r = read(), k = read();
int ne = get_pre_next(l, r, k, "next");
cout << ne << endl;
}
}
return 0;
}