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:
", ++cas );
        for ( int i = 0; i < Q; ++i )
            printf( "%d
", ans[i] );
    }
    return 0;
}

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

原文地址:https://www.cnblogs.com/GBRgbr/p/3364358.html