树状数组离线处理方法:
将右端点升序排列, 重复的数每次只统计最后一位就好
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define CLR(a, b) memset(a, (b), sizeof(a))
const int MAXN = 1e6+10;
int c[MAXN], a[MAXN], ans[MAXN], vis[MAXN];
int n;
struct node {
int l, r;
int id;
}p[MAXN];
bool cmp(const node& a, const node& b) {
return a.r < b.r;
}
int lowbit(int x) { return x&-x; }
void add(int p, int x) { while(p <= n) c[p]+=x, p+=lowbit(p); }
int query(int p) { int res = 0; while(p) res+=c[p],p-=lowbit(p); return res;}
int main(int argc, char const *argv[])
{
//ios::sync_with_stdio(false);
while(~scanf("%d",&n)) {
CLR(vis, false); CLR(c, 0);
for(int i = 1; i <= n; ++i)
scanf("%d",&a[i]);
int q;
cin >> q;
for(int i = 1; i <= q; ++i) {
scanf("%d %d",&p[i].l, &p[i].r);
p[i].id = i;
}
sort(p+1, p+1+q, cmp);
int k = 1;
for(int i = 1; i <= n; ++i) {
if(k > q) break;
if(vis[a[i]]) add(vis[a[i]], -1);
vis[a[i]] = i;
add(i,1);
while(i == p[k].r) {
ans[p[k].id] = query(i)-query(p[k].l-1);
k++;
}
}
for(int i = 1; i <= q; ++i)
printf("%d\n", ans[i]);
}
return 0;
}
主席树在线: