数据结构--莫队算法

Problem Description

https://www.luogu.com.cn/problem/P1972
HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,

因此,他的项链变得越来越长。

有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题

Analysis of ideas

题意就是询问一个区间内,不同的数字有多少个

莫队的精髓就是分块,对于这些区间,给每个区间的右端点分块,同一个块内按区间左端点排序,然后移动双指针来回跳动

莫队的时间复杂度\(O(n \sqrt n)\)

莫队的模板

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define int long long
#define ll __int128_t
const int inf = 0x3f3f3f3f;
const int maxn = 1001110;
const int M = 1e9+7;
int n,m;

int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
    return f*x;
}

void print(int x)
{
    if(x < 0) {putchar('-');x = -x;}
    if(x/10) print(x/10);
    putchar(x%10+'0');
}

int a[maxn];

int pos[maxn];

int ans[maxn];

int cnt[maxn];

struct node
{
    int l,r,id;
    bool operator < (const node tmp) const{
        if(pos[l] == pos[tmp.l]) return r < tmp.r;
        return pos[l] < pos[tmp.l];
    }
}q[maxn];


int res;

void del(int x)
{
    cnt[x]--;
    if(cnt[x] == 0) res--;
}

void add(int x)
{   
    if(cnt[x] == 0) res++;
    cnt[x]++;
}

signed main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("data.in", "r", stdin);
#endif
    n = read();
    int t = sqrt(n);
    for(int i = 1; i <= n; i++) 
    {
        a[i] = read();
        pos[i] = i/t;
    }
    m = read();
    for(int i = 1; i <= m; i++) 
    {
        q[i].l = read();q[i].r = read();
        q[i].id = i;
    }
    sort(q+1,q+1+m);
    int l = 1,r = 0;
    for(int i = 1; i <= m; i++) 
    {
        while(l < q[i].l)
        {
            del(a[l]);
            l++;
        }
        while(l > q[i].l)
        {   
            l--;
            add(a[l]);
        }
        while(r > q[i].r)
        {
            del(a[r]);
            r--;
        }
        while(r < q[i].r)
        {
            r++;
            add(a[r]);
        }
        ans[q[i].id] = res;
    }
    for(int i = 1; i <= m; i++) 
    {
        print(ans[i]);putchar('\n');
    }
    return 0;
}

参考博客

https://www.cnblogs.com/WAMonster/p/10118934.html

posted @ 2020-01-25 09:40  hezongdnf  阅读(137)  评论(0编辑  收藏  举报