描述
Given a sequence of n numbers a1, a2, …, an and a number of
d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each
d-query (i, j), you have to return the number of distinct elements in
the subsequence ai, ai+1, …, aj.
Input
Line 1: n (1 ≤ n ≤ 30000). Line 2: n numbers a1, a2, …, an (1 ≤ ai ≤
106). Line 3: q (1 ≤ q ≤ 200000), the number of d-queries. In the next
q lines, each line contains 2 numbers i, j representing a d-query (1 ≤
i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the
subsequence ai, ai+1, …, aj in a single line.
Input
5
1 1 2 1 3
3
1 5
2 4
3 5
Output
3
2
3
思路
题意是给你n个数,再给你m个查询,每次查询一个[l,r]
,求询问的区间内有多少种不同的数字。
这个题可以使用离线处理+树状数组的方式来处理。
首先记录一下每一个查询,然后按照查询的右端点从小到大排序,然后然后依次处理每个区间
树状数组维护以r为结尾的区间元素种类数,从下标1开始扫描,扫描到排序后的第一个区间的右端点,如果当前数字出现过,就在树状数组原先对应位置-1,然后在新的对应位置+1,然后更新当前元素出现的位置。然后每一个区间的结果就是新的sum[r]-sum[l-1],离线保存起来.
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#include <list>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 3e5 + 10;
const int inf = 0x3f3f3f3f;
int a[N], n, m, ans[N], c[N];
map<int, int> mp;
int lowbit(int x)
{
return x & -x;
}
void add(int i, int k)
{
while (i <= n)
{
c[i] += k;
i += lowbit(i);
}
}
int sum(int i)
{
int res = 0;
while (i > 0)
{
res += c[i];
i -= lowbit(i);
}
return res;
}
struct node
{
int l, r, id;
} query[N];
bool cmp(node x, node y)
{
return x.r < y.r;
}
int main()
{
// freopen("in.txt", "r", stdin);
while (~scanf("%d", &n))
{
mem(c, 0);
mp.clear();
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
scanf("%d%d", &query[i].l, &query[i].r);
query[i].id = i;
}
sort(query, query + m, cmp);
int cur = 1; //从下标为1的位置开始扫描
for (int i = 0; i < m; i++)
{
for (int j = cur; j <= query[i].r; j++)
{
if (mp.find(a[j]) != mp.end())
{
add(mp[a[j]], -1);
}
add(j, 1);
mp[a[j]] = j;
}
cur = query[i].r + 1;
ans[query[i].id] = sum(query[i].r) - sum(query[i].l - 1);
}
for (int i = 0; i < m; i++)
printf("%d\n", ans[i]);
}
return 0;
}