牛客网暑期ACM多校训练营(第一场) J (莫队算法)

题目链接:https://www.nowcoder.com/acm/contest/139/J

 

题目大意:给一个序列,进行q次查询,问1~l和r~n中有多少个不同的数字

 

题目思路:之前只是听说过莫队算法的大名,没有学过,所以看到这道题完全没想法。后来了解了莫队算法以后,这尼玛不就是莫队裸题吗......

莫队算法可以用来解决在序列不修改情况下进行q次询问的几乎所有问题(知乎说的,水平太低还不能确定这句话的准确性..)莫队算法是一种离线算法,有人说他是一种优雅的暴力,我觉得说的很贴切。他是一种离线算法。先记录所有的询问,然后根据恰当的顺序解决问题来减少时间。恰当的顺序使用的是分块,先根据每个询问的l来把询问放到各自的块,然后在块内对r进行排序,本题是从大到小,因为这道题是问r~n有多少个不同的数字。从大到小就直接从右往左走就好,如果从小到大排序,那就需要先跑到最小的地方再往外面跑,浪费时间。然后就有俩变量l r来表示当前准备的区间,然后根据询问不断调整l r即可。详细看代码。时间复杂度是(n^1.5),具体证明方法可参照其他博客......分块的默认大小是sqrt(n),本题如果用的话会tle,这种情况下需要尝试把块改大,亲测改成1000能过。

 

以下是代码:

#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define MAXN 100005
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
int a[MAXN],cnt,num[MAXN],block,bel[MAXN],ans[MAXN];
struct node{
    int l,r,id;
}q[MAXN];
int cmp(node x,node y){
    if(bel[x.l]==bel[y.l])return x.r>y.r;
    return bel[x.l]q[i].l)del(a[l--]);
            while(rq[i].r)add(a[--r]);
            ans[q[i].id]=cnt;
        }
        rep(i,1,m)printf("%d\n",ans[i]);
    }
    return 0;
}

 

你可能感兴趣的:(莫队算法)