DQUERY - D-query
English | Vietnamese |
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.
Example
Input 5 1 1 2 1 3 3 1 5 2 4 3 5 Output 3 2 3
/*
题意:给n个数,m次查询,求[l,r]之间不重复的个数
思路:主席树,利用spos记录每个值在当前操作下最新
的位置,从前往后插入主席树(不需要离散),对于
查询[l,r],我们只要用root[r]的r减去root[r]的l
的个数就可以了。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int a[maxn],root[maxn],spos[maxn];
int n,m,cnt;
vector<int> v;
struct node{
int l,r,sum;
}T[maxn*25];
void update(int l,int r,int &x,int y,int pos,int add){
T[++cnt]=T[y];
T[cnt].sum+=add;
x=cnt; //修改root[i]所指的根节点
if(l==r) return ; //更新完成
int mid = (l+r)>>1;
if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos,add);
else update(mid+1 ,r ,T[x].r,T[y].r,pos,add);
}
int query(int l,int r,int x,int pos){
if(l==r) return T[x].sum;
int mid = (l+r)>>1;
int res=0;
if(mid >= pos){
res=query(l,mid,T[x].l,pos);
}else{
res+=T[T[x].l].sum;
res+=query(mid+1,r,T[x].r,pos);
}
return res;
}
int main(){
int l,r;
v.clear();
memset(spos,0,sizeof spos);
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
v.push_back(a[i]);
}
for(int i=1;i<=n;i++){
update(1,n,root[i],root[i-1],i,1);
if(spos[a[i]]!=0) update(1,n,root[i],root[i],spos[a[i]],-1);//将第i的版本之前重复的相应位置减去
spos[a[i]]=i;
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%d%d",&l,&r);
if(l==1) printf("%d\n",query(1,n,root[r],r)); //注意点,query二分不完善
else {
//root只能通过第r个求出与前面第1到r-1的不同个数
int ans=query(1,n,root[r],r)-query(1,n,root[r],l-1);
printf("%d\n",ans);
}
}
}