给出一段序列,每次修改某个数的值和询问区间第 k 小。\((1\le n,m\le 10^5,0\le a_i\le10^9)\)
分析
动态主席树裸题。
树状数组套主席树,树状数组的每个结点相当于一棵主席树,每次修改操作只在对应树状数组的 logn 个结点所对应的主席树上修改,查询时,将 l - 1 和 r 分别对应的 logn 棵主席树作差即可。
时间复杂度: \(O(n\log^2{n})\)
空间复杂度: \(O(n\log{n})\)
代码
#include <bits/stdc++.h>
#define N 100005
#define lowbit(i) i&-i
#define REP(i, l, r) for (int i = (l); i != (r); ++i)
#define FOR(i, l, r) for (int i = (l); i <= (r); ++i)
#define DRP(i, l, r) for (int i = (l); i != (r); --i)
#define DFR(i, l, r) for (int i = (l); i >= (r); --i)
using namespace std;
int gi() {
int x = 0, f = 1; char c = getchar();
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
struct updates { int a, b, k, d; } q[N];
int n, m, tot, len, sx, sy;
int s[N], hs[N << 1], rx[N], ry[N];
int rt[N], cnt[N << 10], L[N << 10], R[N << 10];
void insert(int lst, int &now, int l, int r, int k, int v) {
if (!now) now = ++tot;
cnt[now] = cnt[lst] + v;
if (l == r) return;
int mid = l + r >> 1;
if (k <= mid) R[now] = R[lst], insert(L[lst], L[now], l, mid, k, v);
else L[now] = L[lst], insert(R[lst], R[now], mid + 1, r, k, v);
}
void modify(int i, int v) {
int k = lower_bound(hs + 1, hs + 1 + len, s[i]) - hs;
while (i <= n) {
insert(rt[i], rt[i], 1, len, k, v);
i += lowbit(i);
}
}
void get(int x, int y) {
sx = sy = 0;
while (x) rx[++sx] = rt[x], x -= lowbit(x);
while (y) ry[++sy] = rt[y], y -= lowbit(y);
}
int query(int l, int r, int k) {
if (l == r) return l;
int sum = 0;
FOR(i, 1, sx) sum -= cnt[L[rx[i]]];
FOR(i, 1, sy) sum += cnt[L[ry[i]]];
int mid = l + r >> 1;
if (k <= sum) {
FOR(i, 1, sx) rx[i] = L[rx[i]];
FOR(i, 1, sy) ry[i] = L[ry[i]];
return query(l, mid, k);
}
else {
FOR(i, 1, sx) rx[i] = R[rx[i]];
FOR(i, 1, sy) ry[i] = R[ry[i]];
return query(mid + 1, r, k - sum);
}
}
int main() {
char ch;
len = n = gi(), m = gi();
FOR(i, 1, n) s[i] = hs[i] = gi();
FOR(i, 1, m) {
cin >> ch;
if (ch == 'Q') q[i] = (updates){gi(), gi(), gi(), 1};
else q[i] = (updates){gi(), hs[++len] = gi(), 0, 0};
}
sort(hs + 1, hs + 1 + len);
len = unique(hs + 1, hs + 1 + len) - hs - 1;
FOR(i, 1, n) modify(i, 1);
FOR(i, 1, m) {
if (q[i].d) {
get(q[i].a - 1, q[i].b);
printf("%d\n", hs[query(1, len, q[i].k)]);
}
else {
modify(q[i].a, -1);
s[q[i].a] = q[i].b;
modify(q[i].a, 1);
}
}
return 0;
}
原文地址:https://www.cnblogs.com/hlw1/p/12257988.html
时间: 2024-10-07 19:15:04