zoukankan      html  css  js  c++  java
  • 数据结构--莫队算法

    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('
    ');
        }
        return 0;
    }
    

    参考博客

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

  • 相关阅读:
    可汗学院的数学从零开始学习顺序?
    判断两个数组内容是否相同
    eclipse package,source folder,folder区别及相互转换
    [垂直化搜索引擎]lucene简介及使用
    有效处理Java异常三原则
    ZeroMQ作者于昨天下午宣布选择安乐死
    linux一路填坑...
    gcc/g++/makefile/easymake/cmake/xmake/nmake ...
    RTSP客户端接收存储数据(live555库中的openRTSP实例)
    RTSP客户端接收存储数据(live555库中的testRTSPClient实例)
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12293899.html
Copyright © 2011-2022 走看看