莫队(不带修改)模板

给你一段序列,每次询问一段区间
问区间内存在多少个不同的数?
输入:
n
a[1],a[2].................a[n]
m
l1,r1
l2,r2
.....
.....
....
ln,rn
样例:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
----------
2
2
4

 代码:

重点:排序方式:(1)左端点所在的块 (2)右端点

先向外扩,再往里缩

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #define ll long long
 6 #define inf 2147483600
 7 using namespace std;
 8 inline int read()
 9 {
10    int x=0,w=1;char ch=getchar();
11    while(!isdigit(ch)){if(ch=='-') w=-1;ch=getchar();}
12    while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
13    return x*w;
14 }
15 const int N=50033;
16 int n,a[N],cnt[1000099];
17 struct query{
18     int l,r,id;
19 }q[200044];
20 int bg[N],block,m,ans[200044];
21 bool cmp(query x,query y)
22 {
23     if(bg[x.l]==bg[y.l]) return x.r<y.r;
24     else return bg[x.l]<bg[y.l];
25 }
26 int l=1,r,tot;
27 int main()
28 {
29     n=read();block=sqrt(n);
30     for(int i=1;i<=n;++i) a[i]=read(),bg[i]=(i-1)/block+1;
31     m=read();
32     for(int i=1;i<=m;++i) 
33      q[i].l=read(),q[i].r=read(),q[i].id=i;
34     sort(q+1,q+m+1,cmp);
35     for(int i=1;i<=m;++i)
36     {
37         while(l<q[i].l)
38         {
39             cnt[a[l]]--;
40             if(cnt[a[l]]==0) tot--;
41             l++;
42         }
43         while(l>q[i].l)
44         {
45             l--;
46             if(cnt[a[l]]==0) tot++;
47             cnt[a[l]]++;
48         }
49         while(r<q[i].r)
50         {
51             r++;
52             if(cnt[a[r]]==0) tot++;
53             cnt[a[r]]++;
54         }
55         while(r>q[i].r)
56         {
57             cnt[a[r]]--;
58             if(cnt[a[r]]==0) tot--;
59             r--;
60         }
61         ans[q[i].id]=tot;
62     }
63     for(int i=1;i<=m;++i) 
64      printf("%d\n",ans[i]);
65     return 0;
66 }
View Code

 

posted @ 2018-03-31 18:46  月亮茶  阅读(164)  评论(0编辑  收藏  举报