题目链接:传送门
题目大意:一个容量 n 的数组, m次询问,每次询问 [x,y]内不同数的个数
题目思路:主席树(注意不是权值线段树而是位置线段树)
也就是按一般线段树的逻辑来写只是用主席树实现而已
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 55005 #define maxn 30010 typedef pair<int,int> PII; typedef long long LL; LL read(){ LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int n,m,k,ans,v,a[N],b[N],L,R; int loc[N],root[N<<1],sz; map<int,int>M; struct Node{int l,r,v;}seg[N*25]; void update(int &rot,int rt,int l,int r,int pos){ seg[++sz]=seg[rot],rot=sz; seg[rot].v+=v; if(l==r)return; int mid=l+r>>1; if(pos<=mid)update(seg[rot].l,lson,pos); else update(seg[rot].r,rson,pos); } int query(int rt,int l,int r,int x,int y,int rot){ if(x<=l&&r<=y)return seg[rot].v; int mid=l+r>>1; int temp=0; if(x<=mid)temp+=query(lson,x,y,seg[rot].l); if(y>mid) temp+=query(rson,x,y,seg[rot].r); return temp; } int main(){ int i,j,group,x,y,Case=0; n=read(); for(i=1;i<=n;++i)a[i]=read(),b[i]=a[i]; sort(b+1,b+n+1); int _n=unique(b+1,b+n+1)-b-1; for(i=1;i<=_n;++i)M[b[i]]=i; for(i=1;i<=n;++i){ v=1; if(!loc[M[a[i]]])update(root[i]=root[i-1],1,1,n,i); else{ int temp; v=-1;update(temp=root[i-1],1,1,n,loc[M[a[i]]]); v=1;update(root[i]=temp,1,1,n,i); } loc[M[a[i]]]=i; } m=read(); for(i=1;i<=m;++i){ x=read(),y=read(); printf("%d ",query(1,1,n,x,y,root[y])); } return 0; }