[BZOJ](1878)HH的项链 ---- 莫队算法

版权声明:本文为博主原创文章,转载请预先通知博主(〃'▽'〃)。 https://blog.csdn.net/m0_37624640/article/details/81393503

Problem 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

 

题意:让你在区间[L,R]中找到有几种不同的数

思路:如果暴力,那么时间复杂度是O(N*M),一定超时。所以借此机会学习莫队算法(真正的神犇,莫涛老师的算法)

莫队算法就是用来处理一类无修改的离线区间询问问题。(来自莫涛大大)

感觉讲的不错的几个博客:

1.莫队算法~讲解

2.莫队算法良心讲解

3.莫队算法 (Mo's Algorithm)

通过学习莫队,于是找了这道入门题。

大致理解思路,敲了一下,感觉很神奇。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
const int maxm = 2e5+5;
struct query{
    int l;
    int r;
    int id;
};
query e[maxm];
int a[maxn];
int cnt[maxn];
int ans[maxn];
int block;//分块数
int now = 0;
int curL = 1;
int curR = 1;
//int read(){
//    char x;
//    while((x = getchar()) > '9' || x < '0') ;
//    int u = x - '0';
//    while((x = getchar()) <= '9' && x >= '0') u = (u << 3) + (u << 1) + x - '0';
//    return u;
//}
bool cmp(query a,query b)
{
    return (a.l/block == b.l/block)?a.r<b.r:a.l<b.l;
}
void add(int pos)
{
    if(++cnt[a[pos]] == 1) ++now;
}
void del(int pos)
{
    if(--cnt[a[pos]] == 0) --now;
}
int main()
{
    #ifdef LOCAL_FILE
    freopen("in.txt","r",stdin);
    #endif // LOCAL_FILE
    int n,m;
    scanf("%d",&n);
    block = (int)sqrt(n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&e[i].l,&e[i].r);
        e[i].id = i;
    }
    sort(e+1,e+1+m,cmp);
    add(1);//将第一个数字的位置1先加入
    for(int i=1;i<=m;i++)
    {
        int L = e[i].l;
        int R = e[i].r;
        while(curL<L) del(curL++);
        while(curL>L) add(--curL);
        while(curR<R) add(++curR);
        while(curR>R) del(curR--);
        ans[e[i].id] = now;
    }
    for(int i=1;i<=m;i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页