题目:https://www.acwing.com/problem/content/2494/
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
//#include <unordered_map>
//#include <unordered_set>
//#include <bits/stdc++.h>
//#define int long long
#define pb push_back
#define PII pair<int, int>
#define mpr make_pair
#define ms(a, b) memset((a), (b), sizeof(a))
#define x first
#define y second
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
const int N = 50010, M = 200010, S = 1000010;
int n, m, len;
int w[N], ans[M]; // w存输入的n个数,ans存询问的那个答案
struct node {
int id, l, r; // id代表第几个询问
} q[M]; //记录询问
int cnt[S]; //记录这个数在这个区间出现了几次
//分块函数
int get(int x) { return x / len; }
//先按照块排序,块内在按照r排序,排序方式分奇偶会更快一些
bool cmp(const node &a, const node &b) {
int i = get(a.l), j = get(b.l); //得到块的编号
if (i != j) return i < j;
if (i % 2 == 0) return a.r < b.r; //分奇偶会快一点
return a.r > b.r;
}
//增加判断
void add(int x, int &res) {
if (!cnt[x]) res++;
cnt[x]++;
}
//减小判断
void del(int x, int &res) {
cnt[x]--;
if (!cnt[x]) res--;
}
// signed main(){
int main(int argc, char const *argv[]) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
len = sqrt(n);
scanf("%d", &m);
for (int i = 0; i < m; i++) {
int l, r;
scanf("%d%d", &l, &r);
q[i] = {i, l, r};
}
// int res = 0;
sort(q, q + m, cmp); //根据规则排序
for (int k = 0, i = 0, j = 1, res = 0; k < m; k++) {
int id = q[k].id, l = q[k].l, r = q[k].r;
while (i < r) add(w[++i], res); // i代表右端点,j代表左端点
while (i > r) del(w[i--], res); //初始i<j代表没区间
while (j < l) del(w[j++], res);
while (j > l) add(w[--j], res);
ans[id] = res;//记录答案
}
for (int i = 0; i < m; i++) {
printf("%d\n", ans[i]);
}
return 0;
}