题意:给定n个数,m个询问,每次回答某个区间内不相同的元素个数。
思路:这道题很像之前hdu上做过的一道 http://blog.csdn.net/u014664226/article/details/47307779
这是用树状数组离线做的,将询问排序,从头扫一遍,将将当前元素上次的出现的位置减一,本次出现的位置加一,如果该点有询问,记录答案。
今天学习了主席树,又用主席树做了一遍,思路和树状数组差不多。
主席树建新树的时候,如果当前元素出现过,那么把这个元素上次出现的位置减一,然后当前位置加一,如果没出现过就是普通的建树操作。
对于查询[l, r]我们只需要取出第r棵树,然后输出这棵树[l,r]之间的和即可。
这道题两种做法时间复杂度都是O(n*logn)。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
//const int maxn = 100000 + 100;
//const int INF = 0x3f3f3f3f;
const int maxn = 50000;
const int M = 15*maxn;
int n, q, m, tot;
int a[maxn];
int T[maxn], lson[M], rson[M], c[M];
map<int, int> vis;
int build(int l, int r) {
int root = tot++;
c[root] = 0;
if(l != r) {
int mid = (l+r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid+1, r);
}
return root;
}
int Insert(int root, int pos, int val) {
int newroot = tot++, tmp = newroot;
int l = 1, r = n;
c[newroot] = c[root] + val;
while(l < r) {
int mid = (l+r)>>1;
if(pos <= mid) {
lson[newroot] = tot++; rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r = mid;
}
else {
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid+1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int Query(int root, int p, int l, int r) {
if(l == p) return c[root];
int mid = (l+r) >> 1;
int ans = 0;
if(p <= mid) return Query(lson[root], p, l, mid) + c[rson[root]];
return Query(rson[root], p, mid+1, r);
}
int main() {
//freopen("input.txt", "r", stdin);
while(cin >> n) {
tot = 0;
vis.clear();
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
T[0] = build(1, n);
for(int i = 1; i <= n; i++) {
if(!vis.count(a[i])) T[i] = Insert(T[i-1], i, 1), vis[a[i]] = i;
else {
T[i] = Insert(T[i-1], vis[a[i]], -1);
T[i] = Insert(T[i], i, 1);
vis[a[i]] = i;
}
}
cin >> q;
for(int i = 0; i < q; i++) {
int l, r; scanf("%d%d", &l, &r);
printf("%d\n", Query(T[r], l, 1, n));
}
}
return 0;
}