https://vjudge.net/problem/SPOJ-DQUERY
此题连接;
题目大意:给出一个n个数的序列;
接下来有k个询问,每一次询问某一区间里的不同数的个数;
莫队思想:分块 排序 暴力;先将所有询问存储起来,然后玄学排序降低复杂度;
1 #include<cstdio> 2 #include<algorithm> 3 #include<math.h> 4 #include<string.h> 5 #include<queue> 6 using namespace std; 7 const int maxn=1e4+10; 8 int vis[maxn*100]; 9 int a[maxn*3]; 10 int temp; //记录每一个区间的不同数的总数; 11 int block; //分块 12 int ans[maxn*20]; 13 struct node 14 { 15 int l,r,id; 16 }query[maxn*20]; 17 bool cmp(node x,node y) 18 { 19 if(x.l/block!=y.l/block) 20 return x.l<y.l; 21 if(x.l/block&1) //使用波形排序,可进一步的优化 22 return x.r<y.r; 23 return x.r>y.r; 24 } 25 void add(int x) 26 { 27 if(!vis[x]) temp++; 28 vis[x]++; 29 } 30 void Delete(int x) 31 { 32 if(vis[x]==1) temp--; 33 vis[x]--; 34 } 35 int main() 36 { 37 int n,q; 38 scanf("%d",&n); 39 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 40 scanf("%d",&q); 41 for(int i=1;i<=q;i++){ 42 scanf("%d%d",&query[i].l,&query[i].r); 43 query[i].id=i; 44 } 45 block=sqrt(n); 46 temp=0; 47 sort(query+1,query+1+q,cmp); 48 int left=1,right=1; 49 add(a[1]); 50 for(int i=1;i<=q;i++){ 51 while(left<query[i].l) Delete(a[left++]); 52 while(left>query[i].l) add(a[--left]); 53 while(right>query[i].r)Delete(a[right--]); 54 while(right<query[i].r)add(a[++right]); 55 ans[query[i].id]=temp; 56 } 57 for(int i=1;i<=q;i++) 58 printf("%d\n",ans[i]); 59 return 0; 60 }