HDU 4417-Super Mario (Chairman tree + line segment tree/tree array offline processing + division tree)
There are many ways to solve this problem. I first learned about the Chairman tree. Next, we will gradually add the line segment tree offline and tree division questions. The general idea is to give a range.
Given a series, each time you are required to query the number of [L, R] numbers not exceeding K
Chair tree practices:
The most basic is the size of the static column K. Here is the size of the static column <= K, which is almost the same. You need to modify and modify it in the query operation.
Create a size chair tree first, and then make statistics when asking
Number of [1, K] In the Chairman tree of the r tree-number of [1, K] In the Chairman tree of the L-1 tree
Note that the subscript starts from 0, so it is l-R + 1.
The question here is why we use the value of HH [I] to build a new one. Otherwise, we will re. What's the problem?
When building a series, remember to discretization K Series.
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define CLR( a, b ) memset( a, b, sizeof(a) )using namespace std; #define lson l, m, L[o]#define rson m + 1, r, R[o]#define MAXN 100005int L[MAXN << 5], R[MAXN << 5], cnt[MAXN << 5];int root[MAXN];int num[MAXN], H[MAXN], tot;int LL[MAXN], RR[MAXN], HH[MAXN];void PushUp( int o ){ cnt[o] = cnt[ L[o] ] + cnt[ R[o] ];} void Build( int l, int r ,int &o ){ o = tot++; cnt[o] = 0; if( l == r ) return; int m = ( l + r ) >> 1; Build( lson ); Build( rson );}void Update( int fa, int p, int l, int r ,int &o ){ o = tot++; //printf("o = %d\n tot = %d\n",o,tot); L[o] = L[fa]; R[o] = R[fa]; cnt[o] = cnt[fa] + 1; if( l == r ) return; int m = ( l + r ) >> 1; if( p <= m ) Update( L[fa], p, lson ); else Update( R[fa], p, rson ); //PushUp( o );}int Query( int u, int v, int l, int r, int ll,int rr ){ if( ll <= l && r <= rr ){ return cnt[v] - cnt[u]; } int m = ( l + r ) >> 1, ans = 0; if( ll <= m ) ans += Query( L[u], L[v], l, m, ll, rr ); if( rr > m ) ans += Query( R[u], R[v], m + 1, r, ll, rr ); return ans;}void Orz(){ int n, i, h, ans, m, cas, t; scanf( "%d", &t ); for( cas = 1; cas <= t; ++cas ){ scanf( "%d %d", &n,&m ); int size = 0; for( i = 1; i <= n; ++i ){ scanf( "%d", &num[i] ); H[++size] = num[i]; } for( i = 1; i <= m; ++i){ scanf( "%d %d %d", &LL[i], &RR[i], &HH[i] ); H[++size] = HH[i]; } sort( H + 1, H + size + 1 ); size = unique( H + 1, H + size + 1 ) - H - 1; tot = 0; Build( 1, size, root[0] ); for( i = 1; i <= n; ++i ){ num[i] = lower_bound( H + 1, H + size + 1, num[i] ) - H; } for( i = 1; i <= n; ++i ){ Update( root[i-1], num[i], 1, size , root[i] ); } printf( "Case %d:\n", cas ); for( i = 1; i <= m; ++i ){ h = lower_bound( H + 1, H + size + 1, HH[i] ) - H; ans = Query( root[LL[i]], root[RR[i]+1], 1, size, 1, h ); printf( "%d\n", ans ); } } }int main() { Orz(); return 0;}
Chairman tree Solution
# Include <cstdio> # include <cstring> # include <algorithm> # include <iostream> # define CLR (a, B) memset (a, B, sizeof ()) using namespace STD; # define lson L, M, L [O] # define rson m + 1, R, R [O] # define maxn limit 5int L [maxn <5], R [maxn <5], CNT [maxn <5]; int root [maxn]; int num [maxn], H [maxn], TOT; void pushup (int o) {CNT [O] = CNT [L [O] + CNT [R [O];} void build (int l, int R, int & O) {o = tot + +; CNT [O] = 0; If (L = r) return; int M = (L + r)> 1; build (lson ); build (rson);} void Update (int fa, int P, int L, int R, Int & O) {o = tot ++; L [O] = L [fa]; R [O] = R [fa]; CNT [O] = CNT [fa] + 1; if (L = r) return; int M = (L + r)> 1; if (P <= m) Update (L [fa], p, lson ); else Update (R [fa], p, rson); // pushup (o);} int query (int u, int V, int L, int R, int X) {If (L = r) Return (X <L )? 0: CNT [v]-CNT [u]; // we require a number smaller than h in the range [L, R, // then CNT [R]-CNT [L-1] int M = (L + r)> 1; if (x <= m) return query (L [u], L [v], L, M, X ); else return CNT [L [v]-CNT [L [u] + query (R [u], R [v], M + 1, R, x );} void orz () {int N, I, j, H, ANS, M, L, R, Cas, T; scanf ("% d", & T ); for (CAS = 1; CAS <= T; ++ CAS) {scanf ("% d", & N, & M); for (I = 1; I <= N; ++ I) {scanf ("% d", & num [I]); H [I] = num [I];} sort (H + 1, H + n + 1); int size = unique (H + 1, H + n + 1)-h-1; for (I = 1; I <= N; ++ I) {num [I] = lower_bound (H + 1, H + size + 1, num [I])-H;} tot = 0; build (1, size, root [0]); for (I = 1; I <= N; ++ I) {Update (root [I-1], num [I], 1, size, root [I]);} printf ("case % d: \ n", CAS); While (M --) {scanf ("% d", & L, & R, & H); H = upper_bound (H + 1, H + size + 1, h) -h-1; ans = query (root [L], root [R + 1], 1, size, H); printf ("% d \ n ", ans) ;}}int main () {orz (); Return 0 ;}
This is correct.
HDU 4417 Super Mario (Super Mario + Chairman tree + line segment tree/tree array offline processing + division tree)