洛谷 P1972 HH的项链

题意:查询某一区间颜色数

思路:对于固定区间来说,颜色数只与各种颜色第一次出现的位置有关。该位置置1,该颜色其余位置置0.

          维护方法:离线,对查询按左端点排序。 查询下一个颜色的位置需要用到跳跃表next数组

#include 
using namespace std;
typedef long long LL;
typedef pair pii;
typedef pair piii;
const LL maxn =500000 + 100;
const LL maxv =1000000 + 100;
const LL maxq = 500000 + 100;
const LL inf = 0x3f3f3f3f3f3f;
LL vis[maxv],a[maxn],last[maxv],b[maxn],n,ne[maxn],ans[maxq];
vector ve;
void init( LL n ){
    for( LL i = 0;i <= n;i++ ) b[i] = 0;
}
LL lowbit( LL x ){
    return x &(-x);
}
void add( LL x,LL v ){
    for( LL i = x;i <= n;i += lowbit( i ) ){
        b[i] += v;
    }
}
LL ask( LL x ){
    LL re = 0;
    while( x ){
        re += b[x];
        x -= lowbit( x );
    }
    return re;
}
int main()
{
    LL m,x,y;
    scanf("%lld",&n);
    init(n);
    for( LL i = 1;i <= n;i++ ){
        scanf("%lld",&a[i]);
    }
    scanf("%lld",&m);
    for( LL i =1;i <= m;i++ ){
        scanf("%lld%lld",&x,&y);
        ve.push_back( piii( x,pii(y,i) ) );
    }
    sort( ve.begin(),ve.end() );
    memset( vis,0,sizeof( vis ) );
    memset( last,0x3f,sizeof( last ) );
    for( LL i = n;i >= 1;i-- ){
        ne[ i ] = last[ a[i] ];
        last[ a[i] ] = i;
    }
    for( LL i = 1;i <= n;i++ ){
        if( !vis[ a[i] ] ){
            add( i,1 );
            vis[ a[i] ] = 1;
        }
    }
    LL L = 1;
    for( LL i = 0;i < ve.size();i++ ){
        LL l = ve[i].first;
        LL r = ve[i].second.first;
        LL id = ve[i].second.second;
        if( l > L ){
            for( ;L < l;L++ ){
                add( L,-1 );
                if( ne[L] < inf )
                add( ne[L],1 );
            }
        }
        ans[id] = ask( r ) - ask( L-1 );
    }
    for( LL i = 1;i <= m;i++ ){
        printf("%lld\n",ans[i]);
    }
    return 0;
}

 

你可能感兴趣的:(数据结构,树状数组,跳跃表,区间查询问题)