1. 程式人生 > >DQUERY 主席樹求區間中不同數字的個數

DQUERY 主席樹求區間中不同數字的個數

題目大意

給定一個序列,求然後有q次查詢求[L,R]區間中不同數字的個數

解題思路

主席樹模版型別題目,離散化,更新查詢

AC程式碼

#include <cstdio>
#include <iostream>
#include <map>
using namespace std;
const int MX = 1e5+5;
const int N = MX*20;
int n,q,tot;
int A[MX];
int T[N],lson[N],rson[N],sum[N];

int build(int l,int r)
{
    int
rt = tot++; sum[rt] = 0; int mid = (l+r)>>1; if(l!=r) { lson[rt] = build(l,mid); rson[rt] = build(mid+1,r); } return rt; } int update(int rt,int pos,int val) { int nrt = tot++; int tmp = nrt; int l=1,r=n; sum[nrt] = sum[rt] + val; while(l<r) { int
mid = (l+r)>>1; if(pos<=mid) { lson[nrt] = tot++; rson[nrt] = rson[rt]; nrt = lson[nrt]; rt = lson[rt]; r = mid; } else { rson[nrt] = tot++; lson[nrt] = lson[rt]; nrt = rson[nrt]; rt = rson[rt]; l = mid+1
; } sum[nrt] = sum[rt]+val; } return tmp; } int query(int rt,int pos) { int l= 1,r = n,ret = 0; while(pos>l) { int mid = (l+r)>>1; if(pos>mid) { l = mid+1; rt= rson[rt]; } else{ r = mid; ret += sum[rson[rt]]; rt = lson[rt]; } } return ret+sum[rt]; } int main() {freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&A[i]); T[0] = build(1,n); map<int,int>mp; for(int i=1;i<=n;i++) { if(mp.find(A[i])==mp.end()) T[i] = update(T[i-1],i,1); else { int tmp = update(T[i-1],mp[A[i]],-1); T[i] = update(tmp,i,1); } mp[A[i]] = i; } scanf("%d",&q); while(q--) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(T[r],l)); } return 0; }