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题目链接
题意:求区间不同数的个数
离线线段树:同HDU 3333
主席树解法:
其实做法也和离线是一样的,线段树维护的是各个位置是否要存在数,记录各个数出现最右边的位置,删除之前的位置、更新当前位置,相当于把各个数字一直往右靠。
于是这样就从左往右保存了多个版本的线段树信息,查询时就拿出右端点对应版本的线段树进行区间查询。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <queue>
#define mem(p,k) memset(p,k,sizeof(p));
#define rep(a,b,c) for(int a=b;a<c;a++)
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define inf 0x6fffffff
#define ll long long
using namespace std;
const int maxn=50005;
int n,q,tot;
int h[maxn],pos[1000010];
int ls[maxn*20],rs[maxn*20],siz[maxn*20];
void update(int &rt,int pre,int k,int val,int l,int r){
rt=++tot;
ls[rt]=ls[pre];
rs[rt]=rs[pre];
siz[rt]=siz[pre]+val;
if(l==r)return;
int m=(l+r)>>1;
if(k<=m)update(ls[rt],ls[pre],k,val,l,m);
else update(rs[rt],rs[pre],k,val,m+1,r);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R){
return siz[rt];
}
int m=(l+r)>>1,ans=0;
if(m>=L) ans+=query(L,R,l,m,ls[rt]);
if(m<R) ans+=query(L,R,m+1,r,rs[rt]);
return ans;
}
int main(){
tot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){
int num;
scanf("%d",&num);
if(pos[num]){
update(h[i],h[i-1],pos[num],-1,1,n);
update(h[i],h[i],i,1,1,n);
}
else update(h[i],h[i-1],i,1,1,n);
pos[num]=i;
}
scanf("%d",&q);
while(q--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r,1,n,h[r]));
}
return 0;
}