SPOJ

来源:互联网 发布:50而知天命什么意思 编辑:程序博客网 时间:2024/06/08 16:24

题目链接


题意:

给你n 个数,给你q个询问,每个询问问你某个区间上不同数的个数是多少?


思路:

q那么大,a[i]最大值为1e6可以想到用离线和BIT来处理.将所有询问记录,按右端点升序排序,对于一个a[i]如果在前面被更新过了,那么就把他删除,在新的位置更新.再处理没超过该范围的所有的区间,最后输出即可.


#include<bits/stdc++.h>#define P pair<int,int>using namespace std;typedef long long ll;const int mod=1e9+7;const int maxn=1e6+10;int s[maxn],n,q;int sum[maxn],vis[maxn],a[maxn];struct node{int l,r,id;bool operator <(const node & w) const{return r < w.r;}}b[maxn];int lowbit(int x) {return x&-x;}void add(int x,int d){while(x < maxn) {s[x] += d;x += lowbit(x);}return ;}int get_sum(int x){int res = 0;while(x){res += s[x];x -= lowbit(x);}return res;}int main(){while(~scanf("%d",&n)){memset(s,0,sizeof s);memset(vis,0,sizeof vis);for(int i = 1;i <= n;++i){scanf("%d",&a[i]);}scanf("%d",&q);for(int i = 1;i <= q;++i){  scanf("%d %d",&b[i].l,&b[i].r);  b[i].id = i;}sort(b+1,b+1+q);int cur = 1;for(int i = 1;i <= n &&cur <= q;++i){if(vis[a[i]])add(vis[a[i]],-1);vis[a[i]] = i;add(vis[a[i]],1);while(cur <= q && b[cur].r <= i){sum[b[cur].id] = get_sum(b[cur].r) - get_sum(b[cur].l-1);cur++;}}for(int i = 1;i <= q;++i)             printf("%d\n",sum[i]);}return 0;}