无
HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。
输入格式:
第一行:一个整数N,表示项链的长度。
第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。
第三行:一个整数M,表示HH 询问的个数。
接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
输出格式:
M 行,每行一个整数,依次表示询问对应的答案。
输入样例#1:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
输出样例#1:
2
2
4
数据范围:
对于100%的数据,N <= 50000,M <= 200000。
题目链接:https://www.luogu.org/problem/show?pid=1972
分析:莫队算法经典题,算是模版题吧!学习一下!
下面给出AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 const int maxn=1001010;
4 typedef long long ll;
5 int n,m,unit;
6 inline int read()
7 {
8 int x=0,f=1;
9 char ch=getchar();
10 while(ch<'0'||ch>'9')
11 {
12 if(ch=='-')
13 f=-1;
14 ch=getchar();
15 }
16 while(ch>='0'&&ch<='9')
17 {
18 x=x*10+ch-'0';
19 ch=getchar();
20 }
21 return x*f;
22 }
23 inline void write(int x)
24 {
25 if(x<0)
26 {
27 putchar('-');
28 x=-x;
29 }
30 if(x>9)
31 {
32 write(x/10);
33 }
34 putchar(x%10+'0');
35 }
36 struct Query
37 {
38 int L,R,id;
39 }node[maxn];
40 ll gcd(ll a,ll b)///求最大公约数
41 {
42 return b==0?a:gcd(b,a%b);
43 }
44 struct Ans
45 {
46 ll a,b;
47 void reduce()///分数简化操作
48 {
49 ll d=gcd(a,b);
50 a/=d;
51 b/=d;
52 }
53 }ans[maxn];
54 bool cmp(Query a,Query b)///把1~n分成sqrt(n)段,unit=sqrt(n)m个查询先按照第几个块排序,再按照R排序,分块处理
55 {
56 if(a.L/unit!=b.L/unit)
57 return a.L/unit<b.L/unit;
58 else return a.R<b.R;
59 }
60 int a[maxn];
61 int num[maxn];
62 inline void work()
63 {
64 ll temp=0;
65 memset(num,false,sizeof(num));
66 int L=1;
67 int R=0;
68 for(int i=0;i<m;i++)///莫队算法核心部分
69 {
70 while(R<node[i].R)
71 {
72 R++;
73 ///temp-=(ll)num[a[R]]*num[a[R]];
74 ///num[a[R]]++;
75 ///temp+=(ll)num[a[R]]*num[a[R]];
76 if(!num[a[R]])
77 temp++;
78 num[a[R]]++;
79 }
80 while(R>node[i].R)
81 {
82 ///temp-=(ll)num[a[R]]*num[a[R]];
83 num[a[R]]--;
84 ///temp+=(ll)num[a[R]]*num[a[R]];
85 ///R--;
86 if(!num[a[R]])
87 temp--;
88 R--;
89 }
90 while(L<node[i].L)
91 {
92 ///temp-=(ll)num[a[L]]*num[a[L]];
93 num[a[L]]--;
94 ///temp+=(ll)num[a[L]]*num[a[L]];
95 ///L++;
96 if(!num[a[L]])
97 temp--;
98 L++;
99 }
100 while(L>node[i].L)
101 {
102 L--;
103 ///temp-=(ll)num[a[L]]*num[a[L]];
104 ///num[a[L]]++;
105 ///temp+=(ll)num[a[L]]*num[a[L]];
106 if(!num[a[L]])
107 temp++;
108 num[a[L]]++;
109 }
110 ans[node[i].id].a=temp;
111 ///ans[node[i].id].b=(ll)(R-L+1)*(R-L);
112 ///ans[node[i].id].reduce();
113 }
114 }
115 int main()
116 {
117 n=read();
118 for(int i=1;i<=n;i++)
119 a[i]=read();
120 m=read();
121 for(int i=0;i<m;i++)
122 {
123 node[i].id=i;
124 node[i].L=read();
125 node[i].R=read();
126 }
127 unit=(int)sqrt(n);
128 sort(node,node+m,cmp);
129 work();
130 for(int i=0;i<m;i++)
131 printf("%lld\n",ans[i].a);
132 return 0;
133 }