题目大意:给你$n$个数,有两个操作:
- $Q\;l\;r\;k:$求出区间$[l,r]$中第$k$大
- $C\;i\;t:$把第$i$个数改成$t$
题解:多人尝试得,现在这道题线段树套线段树过不去,所以我学习了一下树状数组套线段树,线段树只维护值域上的区间和,把树状数组询问部分变成这么多棵线段树相减,这样就可以在线段树上二分了
卡点:无
C++ Code:
#include <cstdio>
#include <cctype>
namespace __IO {
namespace R {
int x, ch;
inline int read() {
ch = getchar();
while (isspace(ch)) ch = getchar();
for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
return x;
}
inline char readc() {
ch = getchar();
while (!isalpha(ch)) ch = getchar();
return static_cast<char> (ch);
}
}
}
using __IO::R::read;
using __IO::R::readc;
#define maxn 100010
#define N (maxn * 400)
const int maxl = 0, maxr = 1e9;
int n, m;
int s[maxn], v[maxn << 1];
namespace SgT {
int V[N], lc[N], rc[N], idx;
int num, op;
void modify(int &rt, int l, int r) {
if (!rt) rt = ++idx;
V[rt] += op;
if (l == r) return ;
int mid = l + r >> 1;
if (num <= mid) modify(lc[rt], l, mid);
else modify(rc[rt], mid + 1, r);
}
int rtL[maxn], rtR[maxn];
int totL, totR;
int query(int l, int r, int k) {
if (l == r) return l;
int tmp = 0, mid = l + r >> 1;
for (int i = 1; i <= totL; i++) tmp -= V[lc[rtL[i]]];
for (int i = 1; i <= totR; i++) tmp += V[lc[rtR[i]]];
if (tmp >= k) {
for (int i = 1; i <= totL; i++) rtL[i] = lc[rtL[i]];
for (int i = 1; i <= totR; i++) rtR[i] = lc[rtR[i]];
return query(l, mid, k);
} else {
for (int i = 1; i <= totL; i++) rtL[i] = rc[rtL[i]];
for (int i = 1; i <= totR; i++) rtR[i] = rc[rtR[i]];
return query(mid + 1, r, k - tmp);
}
}
}
namespace BIT {
int rt[maxn];
void modify(int p, int num, int op = 1) {
SgT::num = num, SgT::op = op;
for (; p <= n; p += p & -p) SgT::modify(rt[p], maxl, maxr);
}
int query(int l, int r, int k) {
l--;
SgT::totL = 0, SgT::totR = 0;
for (int i = l; i; i &= i - 1) SgT::rtL[++SgT::totL] = rt[i];
for (int i = r; i; i &= i - 1) SgT::rtR[++SgT::totR] = rt[i];
return SgT::query(maxl, maxr, k);
}
}
int main() {
n = read(), m = read();
for (int i = 1; i <= n; i++) {
s[i] = read();
BIT::modify(i, s[i]);
}
while (m --> 0) {
char op = readc();
int l = read(), r = read(), k;
if (op == 'Q') {
k = read();
printf("%d\n", BIT::query(l, r, k));
} else {
BIT::modify(l, s[l], -1);
s[l] = r;
BIT::modify(l, s[l]);
}
}
return 0;
}