题目大意:给你$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 ", BIT::query(l, r, k)); } else { BIT::modify(l, s[l], -1); s[l] = r; BIT::modify(l, s[l]); } } return 0; }