题目:http://www.spoj.com/problems/DQUERY/en/
题意:给定一个数组,每次询问一个区间内有多少不同的元素
思路:本题用莫队或者主席树都可以,但是用树状数组离线更快。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 30010;
int bit[N], res[N*10];
int a[N], b[N], vis[N];
int n, m;
struct node
{
int l, r, id;
} g[N*10];
bool cmp(node a, node b)
{
return a.r < b.r;
}
void add(int i, int x)
{
while(i <= n) bit[i] += x, i += i & -i;
}
int sum(int i)
{
int s = 0;
while(i > 0) s += bit[i], i -= i & -i;
return s;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b+1, b+1+n);
for(int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+1+n, a[i]) - b;
scanf("%d", &m);
for(int i = 1; i <= m; i++) scanf("%d%d", &g[i].l, &g[i].r), g[i].id = i;
sort(g+1, g+1+m, cmp);
memset(bit, 0, sizeof bit);
memset(vis, 0, sizeof vis);
int tot = 1;
for(int i = 1; i <= n; i++)
{
if(vis[a[i]] == 0) add(i, 1), vis[a[i]] = i;
else
{
add(vis[a[i]], -1);
add(i, 1);
vis[a[i]] = i;
}
while(tot <= m && g[tot].r == i)
res[g[tot].id] = sum(g[tot].r) - sum(g[tot].l-1), tot++;
}
for(int i = 1; i <= m; i++) printf("%d\n", res[i]);
return 0;
}