一、内容
题意:给定一个序列,和许多区间,查询不同区间内不同数的个数。
二、思路
- 用pre数组记录和当前元素值相同的一个元素的位置,若前面没有则为0。
- 将询问离线保存在node数组里面,按照区间r小的排在前面。查询时,用一now记录更新到的位置,每次更新到这次查询的r处,若前面有相同的元素,把前面位置-1,当前位置+1,这样就只保存了一次。
三、代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 30005;
const int maxq = 2e5 + 5;
struct N{
int l, r, id;
}node[maxq];
bool cmp(N a, N b) {
if (a.r == b.r) return a.l < b.l;
return a.r < b.r;
}
//pre表示当前位置的元素 前面是否有相同的元素 有就代表下标,无就是0
int sum[maxn], a[maxn], pre[maxn], n, q, ans[maxq];
void update(int x, int v) {
for (int i = x; i <= n; i += i & (-i)) {
sum[i] += v;
}
}
int query(int x) {
int ans = 0;
for (int i = x; i > 0; i -= i & (-i)) {
ans += sum[i];
}
return ans;
}
int main() {
scanf("%d", &n);
map<int, int> mp;
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
pre[i] = mp[a[i]];
mp[a[i]] = i;
}
scanf("%d", &q);
for (int i = 1; i <= q; i++) {
scanf("%d%d", &node[i].l, &node[i].r);
node[i].id = i;
}
sort(node + 1, node + 1 + q, cmp);
int now = 1;
for (int i = 1; i <= q; i++) {
while (now <= node[i].r) {
if (pre[now]) {
//删除此位置之前相同的数
update(pre[now], -1);
}
//将此位置的数 + 1
update(now, 1);
now++;
}
ans[node[i].id] = query(node[i].r) - query(node[i].l - 1);
}
for (int i = 1; i <= q; i++) {
printf("%d\n", ans[i]);
}
return 0;
}