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 }
02-13 10:44