# 【树套树】 带修主席树

## Sample

### Limitation

$1 \leq n,~m \leq 10^5$

### Code

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

const int maxn = 100005;

int n, m, upceil;
int MU[maxn];
std::vector<int>tmp;

struct Tree {
Tree *ls, *rs;
int v;

Tree() : ls(NULL), rs(NULL), v(0) {}
};
Tree *rot[maxn];

char ch;
int a, b, c;
};

void init_hash();
void update(int p, const int v);
int Query(int l, int r, int k);
void Update(const int p, const int v);
void query(std::vector<int> &a, int &v);
void update(Tree *const u, const int l, const int r, const int p, const int v);

int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
rot[0] = new Tree;
for (int i = 1; i <= n; ++i) {
rot[i] = new Tree;
qr(MU[i]);
}
char ch; int a, b, c;
for (int M = 1; M <= m; ++M) {
do ch = IPT::GetChar(); while ((ch != 'Q') && (ch != 'C'));
if (ch == 'Q') {
a = b = c = 0; qr(a); qr(b); qr(c);
} else {
a = b = 0; qr(a); qr(b);
}
ask[M] = {ch, a, b, c};
}
init_hash();
for (int i = 1; i <= n; ++i) {
update(i, 1);
}
for (int i = 1; i <= m; ++i) {
if (ch == 'Q') {
qw(Query(a, b, c), '\n', true);
} else {
Update(a, b);
}
}
return 0;
}

void init_hash() {
for (int i = 1; i <= n; ++i) tmp.push_back(MU[i]);
for (int i = 1; i <= m; ++i) if (ask[i].ch == 'C') {
}
std::sort(tmp.begin(), tmp.end());
upceil = std::unique(tmp.begin(), tmp.end()) - tmp.begin();
auto ed = tmp.begin() + upceil;
for (int i = 1; i <= n; ++i) {
MU[i] = std::lower_bound(tmp.begin(), ed, MU[i]) - tmp.begin() + 1;
}
for (int i = 1; i <= m; ++i) if (ask[i].ch == 'C') {
}
}

inline int lowbit(const int x) { return x & -x; }

void update(int p, const int v) {
int pv = MU[p];
do update(rot[p], 1, upceil, pv, v); while ((p += lowbit(p)) <= n);
}

void update(Tree *const u, const int l, const int r, const int p, const int v) {
u->v += v;
if (l == r) return;
int mid = (l + r) >> 1;
if (p <= mid) {
update(u->ls ? u->ls : u->ls = new Tree, l, mid, p, v);
} else {
update(u->rs ? u->rs : u->rs = new Tree, mid + 1, r, p, v);
}
}

void Update(const int p, const int v) {
update(p, -1);
MU[p] = v;
update(p, 1);
}

void query(std::vector<Tree*> &a, int &v) {
if (!a.size()) return;
for (auto u : a) if (u->ls) {
v += u->ls->v;
}
}

void cls(std::vector<Tree*> &a, std::vector<Tree*> &b) {
for (auto u : a) if (u->ls) {
b.push_back(u->ls);
}
}

void crs(std::vector<Tree*> &a, std::vector<Tree*> &b) {
for (auto u : a) if (u->rs) {
b.push_back(u->rs);
}
}

int Query(int l, int r, int k) {
int tl = 1, tr = upceil; --l;
std::vector<Tree*> vl[2], vr[2];
int key = 0, tk = 1;
do vr[0].push_back(rot[r]); while (r -= lowbit(r));
do vl[0].push_back(rot[l]); while (l -= lowbit(l));
while (tl != tr) {
int mid = (tl + tr) >> 1;
int s1 = 0, s2 = 0;
query(vr[key], s1); query(vl[key], s2);
int sum = s1 - s2;
if (sum >= k) {
cls(vr[key], vr[tk]);
cls(vl[key], vl[tk]);
tr = mid;
} else {
crs(vr[key], vr[tk]);
crs(vl[key], vl[tk]);
tl = mid + 1;
k -= sum;
}
vr[key].clear(); vl[key].clear();
std::swap(key, tk);
}
return tmp[tl - 1];
}

posted @ 2019-07-03 00:13  一扶苏一  阅读(741)  评论(0编辑  收藏  举报