1. 程式人生 > >[洛谷P2617]Dynamic Rankings

[洛谷P2617]Dynamic Rankings

題目大意:給你$n$個數,有兩個操作:

  1. $Q\;l\;r\;k:$求出區間$[l,r]$中第$k$大
  2. $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;
}