I haven't written a line segment tree for a year. I can add YY to my memories to make haipi better ..............
A very bare line segment tree requires discretization first.
Discretization I remember lower_bound, but I can't remember how to use it... so here, YY used a map and then the O (n) loop for discrete value correspondence...
Preparation:
1/STL-Unique. Two pointers are accepted (the third parameter is an optional custom equality comparator, and true is returned if the third parameter is equal). The result is a sweep from start to end, use adjacent equal elements (sort is required if not met ). put all elements with repeated intervals to the end and return the last element address of the non-repeating intervals.
template <class ForwardIterator> ForwardIterator unique ( ForwardIterator first, ForwardIterator last ){ ForwardIterator result=first; while (++first != last) { if (!(*result == *first)) // or: if (!pred(*result,*first)) for the pred version *(++result)=*first; } return ++result;}
2/STL-lower_bound, which accepts the two pointers and the value to be searched (the fourth optional parameter is a custom value smaller than the comparator and returns true if it is less than the comparator ), used to find the first element (greater than or equal to a value) not less than (less than or equal to) in an ordered interval ),
Returns the address of the bottom element. Binary point used for visual testing.
template <class ForwardIterator, class T> ForwardIterator lower_bound ( ForwardIterator first, ForwardIterator last, const T& value ){ ForwardIterator it; iterator_traits<ForwardIterator>::distance_type count, step; count = distance(first,last); while (count>0) { it = first; step=count/2; advance (it,step); if (*it<value) // or: if (comp(*it,value)), for the comp version { first=++it; count-=step+1; } else count=step; } return first;}
The following code discretization using unique/lower_bound is provided:
sort(all, all+idx);int tot = unique(all, all+idx) - all;build(1, tot, 1);...int x = lower_bound(all, all+tot, st[i]) - all;int y = lower_bound(all, all+tot, en[i]) - all;
In short, unique is used to remove duplicate elements, and lower_bound is used to find the element position (the intervals after unique are no longer repeated, so they are only searching, so you can even use upper_bound, but upper_bound returns a value greater than value () and does not contain equal values. Therefore, use upper_bound (...) -1, equivalent to lower_bound (...)).
Code (originally ):
# Include <cstdio> # include <cstring> # include <iostream> # include <cmath> # include <string> # include <vector> # include <map> # include <algorithm> using namespace STD; int RINT () {int X; scanf ("% d", & X); Return x ;}# define for (I, a, B) for (INT I = (a); I <= (B); I ++) # define Ford (I, a, B) for (INT I = (); I >= (B); I --) # define rep (x) for (INT I = 0; I <(x); I ++) typedef long int64; # define Inf (1 <30) # define bug (s) cout <# S <"=" <S <"# define maxn 100002 struct node {int L, R, V; int add; // lazy-add} A [maxn * 2*4]; // 1-th // 10 ^ 9 discretization, 10 ^ 5 line segments, up to 2*10 ^ 5 points void Pushdown (int e) {if (a [e]. add) {if (a [e]. l! = A [e]. r) // if it is not a leaf, push down {A [E <1]. add + = A [e]. add; A [E <1 | 1]. add + = A [e]. add; // Pushdown (E <1); // recursive push-down is not allowed. Otherwise, it is not lazy. // Pushdown (E <1 | 1 );} A [e]. V + = A [e]. add; A [e]. add = 0 ;}} void build (int l, int R, int e) {A [e]. L = L; A [e]. R = r; A [e]. V = A [e]. add = 0; If (L = r) {return;} else {int mid = (L + r)> 1; build (L, mid, E <1); Build (Mid + 1, R, e <1 | 1) ;}} void add (int l, int R, int e) {// If (L! = R) // No need to reach the leaf node, otherwise the delay processing will be meaningless, and the efficiency degradation will be required by TLE ~ --If (L <= A [e]. L & A [e]. r <= r) {A [e]. add + = 1;} else {int mid = (a [e]. L + A [e]. r)> 1; if (L <= mid) add (L, R, e <1); If (Mid + 1 <= r) // note that Mid + 1add (L, R, e <1 | 1) ;}} int query (int e, int p) {Pushdown (E ); if (A [e]. L = P & A [e]. R = P) {return a [e]. v;} else {// Pushdown (E); // The push here is not enough... wa1int mid = (a [e]. L + A [e]. r)> 1; if (P <= mid) // is the left side of the MID? Return query (E <1, P); elsereturn query (E <1 | 1, p) ;}} int n, m; // M = query timesint st [maxn], en [maxn]; int Q [maxn]; int all [maxn * 3]; int idx; Map <int, int> tolow; // e.g. tolow [234] = 1; int main () {int T = RINT (); For (T, 1, t) {tolow. clear (); idx = 0; printf ("case # % d: \ n", T); n = RINT (); M = RINT (); rep (N) {st [I] = RINT (); en [I] = RINT (); All [idx ++] = sT [I]; all [idx ++] = en [I];} rep (m) {q [I] = RINT (); All [idx ++] = Q [I];} sort (all, all + idx); int Rank = 1; rep (idx) {int v = All [I]; If (tolow [v]) continue; tolow [v] = rank ++; // The discrete value starts from 1} int tot = tolow. size (); Build (1, TOT, 1); rep (n) {Add (tolow [st [I], tolow [en [I], 1 );} rep (m) {int ans = query (1, tolow [Q [I]); printf ("% d \ n", ANS );}}}
Code (lower_bound ):
# Include <cstdio> # include <cstring> # include <iostream> # include <cmath> # include <string> # include <vector> # include <map> # include <algorithm> using namespace STD; int RINT () {int X; scanf ("% d", & X); Return x ;}# define for (I, a, B) for (INT I = (a); I <= (B); I ++) # define Ford (I, a, B) for (INT I = (); I >= (B); I --) # define rep (x) for (INT I = 0; I <(x); I ++) typedef long int64; # define Inf (1 <30) # define bug (s) cout <# S <"=" <S <"# define maxn 100002 struct node {int L, R, V; int add; // lazy-add} A [maxn * 2*4]; // 1-th // 10 ^ 9 discretization, 10 ^ 5 line segments, up to 2*10 ^ 5 points void Pushdown (int e) {if (a [e]. add) {if (a [e]. l! = A [e]. r) // if it is not a leaf, push down {A [E <1]. add + = A [e]. add; A [E <1 | 1]. add + = A [e]. add; // Pushdown (E <1); // recursive push-down is not allowed. Otherwise, it is not lazy. // Pushdown (E <1 | 1 );} A [e]. V + = A [e]. add; A [e]. add = 0 ;}} void build (int l, int R, int e) {A [e]. L = L; A [e]. R = r; A [e]. V = A [e]. add = 0; If (L = r) {return;} else {int mid = (L + r)> 1; build (L, mid, E <1); Build (Mid + 1, R, e <1 | 1) ;}} void add (int l, int R, int e) {// If (L! = R) // No need to reach the leaf node, otherwise the delay processing will be meaningless, and the efficiency degradation will be required by TLE ~ --If (L <= A [e]. L & A [e]. r <= r) {A [e]. add + = 1;} else {int mid = (a [e]. L + A [e]. r)> 1; if (L <= mid) add (L, R, e <1); If (Mid + 1 <= r) // note that Mid + 1add (L, R, e <1 | 1) ;}} int query (int e, int p) {Pushdown (E ); if (A [e]. L = P & A [e]. R = P) {return a [e]. v;} else {// Pushdown (E); // The push here is not enough... wa1int mid = (a [e]. L + A [e]. r)> 1; if (P <= mid) // is the left side of the MID? Return query (E <1, P); elsereturn query (E <1 | 1, p) ;}} int n, m; // M = query timesint st [maxn], en [maxn]; int Q [maxn]; int all [maxn * 3]; int idx; Map <int, int> tolow; // e.g. tolow [234] = 1; int main () {int T = RINT (); For (T, 1, t) {tolow. clear (); idx = 0; printf ("case # % d: \ n", T); n = RINT (); M = RINT (); rep (N) {st [I] = RINT (); en [I] = RINT (); All [idx ++] = sT [I]; all [idx ++] = en [I];} rep (m) {q [I] = RINT (); All [idx ++] = Q [I];} sort (all, all + idx); int tot = unique (all, all + idx)-All; build (1, TOT, 1); rep (N) {int x = lower_bound (all, all + tot, St [I])-All + 1; int y = lower_bound (all, all + tot, en [I]) -All + 1; add (X, Y, 1);} rep (m) {int x = lower_bound (all, all + tot, Q [I]) -All + 1; int ans = query (1, x); printf ("% d \ n", ANS );}}}
Code (upper_bound ):
# Include <cstdio> # include <cstring> # include <iostream> # include <cmath> # include <string> # include <vector> # include <map> # include <algorithm> using namespace STD; int RINT () {int X; scanf ("% d", & X); Return x ;}# define for (I, a, B) for (INT I = (a); I <= (B); I ++) # define Ford (I, a, B) for (INT I = (); I >= (B); I --) # define rep (x) for (INT I = 0; I <(x); I ++) typedef long int64; # define Inf (1 <30) # define bug (s) cout <# S <"=" <S <"# define maxn 100002 struct node {int L, R, V; int add; // lazy-add} A [maxn * 2*4]; // 1-th // 10 ^ 9 discretization, 10 ^ 5 line segments, up to 2*10 ^ 5 points void Pushdown (int e) {if (a [e]. add) {if (a [e]. l! = A [e]. r) // if it is not a leaf, push down {A [E <1]. add + = A [e]. add; A [E <1 | 1]. add + = A [e]. add; // Pushdown (E <1); // recursive push-down is not allowed. Otherwise, it is not lazy. // Pushdown (E <1 | 1 );} A [e]. V + = A [e]. add; A [e]. add = 0 ;}} void build (int l, int R, int e) {A [e]. L = L; A [e]. R = r; A [e]. V = A [e]. add = 0; If (L = r) {return;} else {int mid = (L + r)> 1; build (L, mid, E <1); Build (Mid + 1, R, e <1 | 1) ;}} void add (int l, int R, int e) {// If (L! = R) // No need to reach the leaf node, otherwise the delay processing will be meaningless, and the efficiency degradation will be required by TLE ~ --If (L <= A [e]. L & A [e]. r <= r) {A [e]. add + = 1;} else {int mid = (a [e]. L + A [e]. r)> 1; if (L <= mid) add (L, R, e <1); If (Mid + 1 <= r) // note that Mid + 1add (L, R, e <1 | 1) ;}} int query (int e, int p) {Pushdown (E ); if (A [e]. L = P & A [e]. R = P) {return a [e]. v;} else {// Pushdown (E); // The push here is not enough... wa1int mid = (a [e]. L + A [e]. r)> 1; if (P <= mid) // is the left side of the MID? Return query (E <1, P); elsereturn query (E <1 | 1, p) ;}} int n, m; // M = query timesint st [maxn], en [maxn]; int Q [maxn]; int all [maxn * 3]; int idx; Map <int, int> tolow; // e.g. tolow [234] = 1; int main () {int T = RINT (); For (T, 1, t) {tolow. clear (); idx = 0; printf ("case # % d: \ n", T); n = RINT (); M = RINT (); rep (N) {st [I] = RINT (); en [I] = RINT (); All [idx ++] = sT [I]; all [idx ++] = en [I];} rep (m) {q [I] = RINT (); All [idx ++] = Q [I];} sort (all, all + idx); int tot = unique (all, all + idx)-All; build (1, TOT, 1); rep (N) {int x = upper_bound (all, all + tot, St [I])-All; // upper_bound: Find the first one greater than value (or comp is true) int y = upper_bound (all, all + tot, en [I])-All; add (X, Y, 1);} rep (m) {int x = upper_bound (all, all + tot, Q [I])-All; int ans = query (1, x); printf ("% d \ n ", ans );}}}