SPOJ - DQUERY(莫队算法)
A - D-query
题意:
给出一个长度为n的序列,询问【l,r】区间一共有多少个不同的元素。
分析:
莫队算法的模板题。
学习资料:大佬博客
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <map> #include <queue> #include <math.h> #include <string> #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; #define ll long long #define ull unsigned long long #define cls(x) memset(x,0,sizeof(x)) #define clslow(x) memset(x,-1,sizeof(x)) const int maxn=3e4+100; const int maxv=1e6+100; const int maxq=2e5+100; int n,q,num,block_size; int arr[maxn],cnt[maxv],ans[maxq]; struct Query { int l,r,id; bool operator < (const Query& rhs) const { if(l/block_size!=rhs.l/block_size){ return l/block_size<rhs.l/block_size; } return r<rhs.r; } }; Query query[maxq]; void add(int pos) { cnt[arr[pos]]++; if(cnt[arr[pos]]==1){ num++; } } void del(int pos) { cnt[arr[pos]]--; if(cnt[arr[pos]]==0){ num--; } } int main() { // freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { num=0; cls(cnt); block_size=sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&arr[i]); } scanf("%d",&q); for(int i=1;i<=q;i++){ query[i].id=i; scanf("%d%d",&query[i].l,&query[i].r); } sort(query+1,query+q+1); int L=query[1].l,R=L-1; for(int i=1;i<=q;i++){ while(L>query[i].l) add(--L); while(L<query[i].l) del(L++); while(R<query[i].r) add(++R); while(R>query[i].r) del(R--); ans[query[i].id]=num; } for(int i=1;i<=q;i++){ printf("%d\n",ans[i]); } } return 0; }