标签:
题目链接:BZOJ - 1901
树状数组套线段树或线段树套线段树都可以解决这道题。
第一层是区间,第二层是权值。
空间复杂度和时间复杂度均为 O(n log n)。
树状数组套线段树
#include <iostream> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; const int MaxN = 10000 + 5, MN = 1000000015, MaxNode = 10000 * 30 * 15 + 15; int n, m, Index, Used_Index; int A[MaxN], Root[MaxN], Son[MaxNode][2], T[MaxNode], U[MaxN], C[MaxN]; void Add(int &x, int s, int t, int Pos, int Num) { if (x == 0) x = ++Index; T[x] += Num; if (s == t) return; int m = (s + t) >> 1; if (Pos <= m) Add(Son[x][0], s, m, Pos, Num); else Add(Son[x][1], m + 1, t, Pos, Num); } void Change(int x, int Pos, int Num) { for (int i = x; i <= n; i += i & -i) Add(Root[i], 0, MN, Pos, Num); } int Get_Sum(int x) { int ret = 0; for (int i = x; i; i -= i & -i) ret += T[Son[U[i]][0]]; return ret; } void Init_U(int x) { for (int i = x; i; i -= i & -i) U[i] = Root[i]; } void Turn(int x, int f) { for (int i = x; i; i -= i & -i) { if (C[i] == Used_Index) break; C[i] = Used_Index; U[i] = Son[U[i]][f]; } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { scanf("%d", &A[i]); Change(i, A[i], 1); } char f; int Pos, Num, L, R, k, Temp; for (int i = 1; i <= m; ++i) { f = ‘-‘; while (f < ‘A‘ || f > ‘Z‘) f = getchar(); if (f == ‘C‘) { scanf("%d%d", &Pos, &Num); Change(Pos, A[Pos], -1); A[Pos] = Num; Change(Pos, Num, 1); } else { scanf("%d%d%d", &L, &R, &k); int l, r, mid; l = 0; r = MN; Init_U(L - 1); Init_U(R); Used_Index = 0; while (l < r) { mid = (l + r) >> 1; Temp = Get_Sum(R) - Get_Sum(L - 1); ++Used_Index; if (Temp >= k) { r = mid; Turn(L - 1, 0); Turn(R, 0); } else { l = mid + 1; k -= Temp; Turn(L - 1, 1); Turn(R, 1); } } printf("%d\n", l); } } return 0; }
[BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
标签:
原文地址:http://www.cnblogs.com/JoeFan/p/4317275.html