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); } } }