Title Link: BZOJ-3196
Problem analysis
The interval kth and interval rank are implemented by the tree array nested segment tree, and the interval precursor successor is implemented by the set of segment tree sets.
In order to save space, need to go offline, first discretization, so that the size of the required array can be smaller, you can pass 128MB =
Well, that's it, code length = = I wrote 260 lines ... Debug N Hours = =
Code
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath > #include <algorithm> #include <set> #include <map>using namespace Std;const int maxn = 50000 + 5, MAXM = 50000 + 5, MN = 100000 +, INF = 999999999, Maxnode = 8000000 + 15;int N, M, Index, Used_index, Top, Hash_index;int A [MAXN], ROOT[MAXN], T[maxnode], son[maxnode][2], U[MAXN], C[MAXN], QUE[MAXN + MAXM], TR[MAXN + maxm];struct Query{int F, L , R, K, Num, Pos;} Q[maxm];map<int, int> m;multiset<int> S[MAXN * 4];multiset<int>::iterator It;inline int gmin (int A, int b) {return a < b a:b;} inline int gmax (int a, int b) {return a > b a:b;} 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);} void add_s (int x, int S, int t, int Pos, int Num) {s[x].insert (num), if (s = = t) return;int m = (s + t) >> 1;if (Pos <= m) add_s (x << 1, S, M, POS, num); else add_s (x << 1 | 1, M + 1, T, POS, num);} void del_s (int x, int S, int t, int Pos, int Num) {s[x].erase (S[x].find (num)), if (s = = t) return;int m = (s + t) >> 1 if (POS <= m) del_s (x << 1, S, M, POS, num); else del_s (x << 1 | 1, M + 1, T, POS, num);} 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 get_lsum (int x) {int ret = 0;for (int i = x; i; i-= i & i) ret + = T[son[u[i]][0]];return ret;} int before (int x, int s, int t, int l, int r, int Num) {int ret;if (l <= s && r >= t) {It = S[x].end (); it--;if (*it < num) return *it;it = S[x].begin (), if (*it >= num) return-inf;it = s[x].Lower_bound (Num); It--;return *it;} int m = (s + t) >> 1;ret =-inf;if (l <= m) ret = Gmax (ret, before (x << 1, S, M, L, R, Num)); if (R >= m + 1) ret = Gmax (ret, before (x << 1 | 1, M + 1, T, L, R, Num)); return ret;} int after (int x, int s, int t, int l, int r, int Num) {int ret;if (l <= s && r >= t) {It = S[x].upper_bound (Nu m); if (It = = S[x].end ()) return inf;else return *it;} int m = (s + t) >> 1;ret = inf;if (l <= m) ret = Gmin (ret, after (x << 1, S, M, L, R, Num)); if (R >= m + 1) ret = Gmin (ret, after (x << 1 | 1, M + 1, T, L, R, Num)); return ret;} int main () {scanf ("%d%d", &n, &m); Top = 0; Index = 0;for (int i = 1; I <= n; ++i) {scanf ("%d", &a[i]); Que[++top] = A[i];} for (int i = 1; I <= m; ++i) {scanf ("%d", &q[i].f), and switch (Q[I].F) {case 1:scanf ("%d%d%d", &q[i]. L, &q[i]. R, &q[i]. Num); Break;case 2:scanf ("%d%d%d", &q[i]. L, &q[i]. R, &Q[I].K); Break;case 3:scanf ("%d%d", &q[i]. Pos&q[i]. Num); Break;case 4:scanf ("%d%d%d", &q[i]. L, &q[i]. R, &q[i]. Num); Break;case 5:scanf ("%d%d%d", &q[i]. L, &q[i]. R, &q[i]. Num); break;} if (q[i].f! = 2) Que[++top] = Q[i]. Num;} Sort (Que + 1, Que + Top + 1); Hash_index = 0;for (int i = 1; I <= Top; ++i) {if (i > 1 && que[i] = = Que[i-1]) continue; M[que[i]] = ++hash_index;tr[hash_index] = Que[i];} for (int i = 1; I <= n; ++i) {a[i] = m[a[i]]; Change (i, A[i], 1); add_s (1, 1, N, I, A[i]);} int L, R, Pos, Num, K, Temp, L, R, Mid; for (int i = 1; I <= m; ++i) {if (q[i].f! = 2) q[i]. Num = M[q[i]. Num];switch (Q[I].F) {case 1:l = q[i]. L R = Q[i]. R Num = Q[i]. Num; Used_index = 0;init_u (L-1); Init_u (R); Temp = 0;l = 0; r = Mn;while (L < r) {++used_index;mid = (L + R) >> 1;if (Num <= mid) {r = Mid; Turn (L-1, 0); Turn (R, 0);} else {Temp + = Get_lsum (R)-get_lsum (L-1); L = mid + 1; Turn (L-1, 1); Turn (R, 1);}} printf ("%d\n", Temp + 1); Break;case 2:l = Q[i]. L R = Q[i]. R K = Q[i].k;init_u (L- 1); Init_u (R); Used_index = 0; Temp = 0;l = 0; r = Mn;while (L < r) {++used_index;mid = (L + r) >> 1; temp = Get_lsum (r)-Get_lsum (L-1); if (Temp >= k) {r = Mid; Turn (L-1, 0); Turn (R, 0);} else {L = mid + 1; Turn (L-1, 1); Turn (R, 1); k-= Temp; }}printf ("%d\n", Tr[l]); break;case 3:P os = q[i]. Pos; Num = Q[i]. Num; Change (POS, A[pos],-1);D el_s (1, 1, N, Pos, A[pos]); A[pos] = Num; Change (Pos, Num, 1); add_s (1, 1, N, Pos, Num); Break;case 4:l = Q[i]. L R = Q[i]. R Num = Q[i]. num;printf ("%d\n", Tr[before (1, 1, N, L, R, Num)]); Break;case 5:l = Q[i]. L R = Q[i]. R Num = Q[i]. num;printf ("%d\n", Tr[after (1, 1, N, L, R, Num)]); return 0;}
[Bzoj 3196] 213 balance Tree "segment tree Set set + Tree array set segment tree"