P2617 Dynamic Rankings
P2617 Dynamic Rankings
题意:
给定一个含有 n个数的序列 a1,a2…an,需要支持两种操作:
Q l r k
表示查询下标在区间 [l,r] 中的第 k 小的数C x y
表示将 ax改为 y
题解:
A:带修改的主席树怎么写?
B:你会树状数组吗?
A: 只到一点点。
B: 如果你会树状数组一分钟就学会了。 普通的主席树是维护1到i每个版本的信息, 类似与前缀和, 树状数组也是维护前缀和的东西, 如果把之前的前缀和换成 树状数组的前缀和就可以再 log(n)的时间修改和查询。
A: 我取研究一下。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 100007;
#define m (l + r) / 2
struct hjt{
int l, r, sum;
}tree[400 * N];
struct qu{
int l, r, k;
}que[N];
int top = 1, n, q, a[N], rt[N];
vector<int>g;
int get_id(int x) {
return lower_bound(g.begin(), g.end(), x) - g.begin() + 1;
}
int lowbit(int x) {
return x&-x;
}
void update(int num, int v, int &now, int l, int r) {
if (!now) now = top++;
tree[now].sum += num;
if (l == r)return;
if (v <= m) update(num, v, tree[now].l, l, m);
else update(num, v, tree[now].r, m + 1, r);
}
int query(int k, vector<int> &last, vector<int> &now, int l, int r) {
if (l == r) return l;
int sum = 0;
for (int i = 0; i < now.size(); i++) {
sum += tree[tree[now[i]].l].sum;
}
for (int i = 0; i < last.size(); i++) {
sum -= tree[tree[last[i]].l].sum;
}
if (sum >= k) {
for (int i = 0; i < now.size(); i++) {
now[i] = tree[now[i]].l;
}
for (int i = 0; i < last.size(); i++) {
last[i] = tree[last[i]].l;
}
return query(k, last, now, l, m);
}
for (int i = 0; i < now.size(); i++) {
now[i] = tree[now[i]].r;
}
for (int i = 0; i < last.size(); i++) {
last[i] = tree[last[i]].r;
}
return query(k - sum, last, now, m + 1, r);
}
void add(int x, int va, int nu) {
while (x <= n) {
update(nu, va, rt[x], 1, (int)g.size());
x += lowbit(x);
}
}
int ask (int l, int r, int k) {
vector<int> last, now;
int x = l - 1;
while (x > 0) {
last.push_back(rt[x]);
x -= lowbit(x);
}
x = r;
while (x > 0) {
now.push_back(rt[x]);
x -= lowbit(x);
}
return query(k, last, now, 1, (int)g.size());
}
int main(){
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
g.push_back(a[i]);
}
for (int i = 1; i <= q; i++) {
char op;
scanf(" %c", &op);
if (op == 'Q') {
int l, r, k;
scanf("%d %d %d", &l, &r, &k);
que[i] = (qu){l, r, k};
} else {
int l, r;
scanf("%d %d", &l, &r);
que[i] = (qu){0, l, r};
g.push_back(r);
}
}
sort(g.begin(), g.end());
g.erase(unique(g.begin(), g.end()), g.end());
for (int i = 1; i <= n; i++) {
int va = get_id(a[i]);
add(i, va, 1);
}
for (int i = 1; i <= q; i++) {
if (que[i].l) {
printf("%d\n" , g[ask(que[i].l, que[i].r, que[i].k) - 1]);
}else{
int va = get_id(a[que[i].r]);
add(que[i].r, va, -1);
va = get_id(que[i].k);
add(que[i].r, va, 1);
a[que[i].r] = que[i].k;
}
}
}