把数值和查询放在一起从小到大排序,纪录每个数值的位置,当遇到数值时就更新到树状数组中,遇到查询就直接查询该区间和。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int MAXN = 200100; struct node { int id; int L, R; int val; } qq[MAXN]; int N, Q; int cntQ; int ans[MAXN/2]; int C[MAXN]; bool cmp( const node& a, const node& b ) { if ( a.val == b.val ) return a.id < b.id; return a.val < b.val; } int lowbit( int x ) { return (-x)&x; } void Update( int x, int v ) { for ( int i = x; i <= N; i += lowbit(i) ) C[i] += v; return; } int Query( int x ) { int res = 0; for ( int i = x; i > 0; i -= lowbit(i) ) res += C[i]; return res; } int main() { int T, cas = 0; scanf( "%d", &T ); while (T--) { scanf( "%d%d", &N, &Q ); memset( C, 0, sizeof(int)*(N+4) ); cntQ = 0; for ( int i = 0; i < N; ++i ) { scanf( "%d", &qq[cntQ].val ); qq[cntQ].L = i + 1; qq[cntQ++].id = -1; } for ( int i = 0; i < Q; ++i ) { scanf( "%d%d%d", &qq[cntQ].L, &qq[cntQ].R, &qq[cntQ].val ); ++qq[cntQ].L, ++qq[cntQ].R; qq[cntQ++].id = i; } sort( qq, qq + cntQ, cmp ); for ( int i = 0; i < cntQ; ++i ) { if ( qq[i].id == -1 ) Update( qq[i].L, 1 ); else ans[ qq[i].id ] = Query( qq[i].R ) - Query( qq[i].L-1 ); } printf( "Case %d: ", ++cas ); for ( int i = 0; i < Q; ++i ) printf( "%d ", ans[i] ); } return 0; }
也可以用在线划分树做……