BZOJ 1878: [SDOI2009]HH的项链

本文介绍了一个关于查询贝壳项链中不同贝壳种类数量的问题解决方案。通过维护nxt和lst数组,并使用线段树或树状数组来高效地计算指定区间内的不同元素数目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 4677 Solved: 2318

Description

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一
段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一
个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只
好求助睿智的你,来解决这个问题。

Input

第一行:一个整数N,表示项链的长度。
第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。
第三行:一个整数M,表示HH询问的个数。
接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
N ≤ 50000,M ≤ 200000。

Output

M行,每行一个整数,依次表示询问对应的答案。

Sample Input

6

1 2 3 4 3 5

3

1 2

3 5

2 6

Sample Output

2

2

4

HINT

Source

Day2


题解:和我写的BZOJ 2743 其实是一道题,我们还是维护nxt数组和lst数组,然后每次利用这两个数组的性质,进行修改即可


#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, maxn, lst[1000005], a[50005], nxt[50005], C[50005], ans[200005];
struct Q { int l, r, id; }q[200005];
bool cmp( const Q &a, const Q &b ) { return a.l < b.l; }
void modify( int x, int v ) { for( ; x <= n; x += x & (-x) ) C[x] += v; }
int query( int x ) { int tmp = 0; for( ; x; x -= x & (-x) ) tmp += C[x]; return tmp; }
int main( ) {
    scanf( "%d", &n );
    for( register int i = 1; i <= n; i++ ) scanf( "%d", &a[i] ), maxn = max( a[i], maxn );
    for( register int i = n; i > 0; i-- ) nxt[i] = lst[a[i]], lst[a[i]] = i;
    for( register int i = 1; i <= maxn; i++ ) if(lst[i]) modify( lst[i], 1 );
    scanf( "%d", &m );
    for( register int i = 1; i <= m; i++ ) scanf( "%d%d", &q[i].l, &q[i].r ), q[i].id = i;
    sort( q + 1, q + m + 1, cmp );
    int l = 1;
    for( register int i = 1; i <= m; i++ ) {
        while( l < q[i].l ) {
            if( nxt[l] ) modify( nxt[l], 1 );
            l++;
        }
        ans[q[i].id] = query( q[i].r )- query( q[i].l - 1 );
    }
    for( register int i = 1; i <= m; i++ ) printf( "%d\n", ans[i] );
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值