[洛谷P2617]Dynamic Rankings
阿新 • • 發佈:2018-11-29
題目大意:給你$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; }