HDU 4417 Super Mario ( 离线树状数组 )

把数值和查询放在一起从小到大排序,纪录每个数值的位置,当遇到数值时就更新到树状数组中,遇到查询就直接查询该区间和。

 

#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:\n", ++cas );

        for ( int i = 0; i < Q; ++i )

            printf( "%d\n", ans[i] );

    }

    return 0;

}

 也可以用在线划分树做……

你可能感兴趣的:(super)