SPOJ - DQUERY 主席树
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32356
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.
题意:给出很多询问,求出每次询问数列中连续区间的不同的数的个数。
算法分析:算法思想是主席树,这个算法真是神奇得没话说,必须得崇拜呀。由于刚接触这个算法思想,所以主席树是参照kuangbin大牛的模板来写的。
引用主席树的发明人说过的两句话:
这个东西是当初我弱不会划分树的时候写出来替代的一个玩意..被一小撮别有用心的人取了很奇怪的名字> < 。
想法是对原序列的每一个前缀[1..i]建立出一颗线段树维护值域上每个数的出现次数,然后发现这样的树是可以减的,然后就没有然后了 。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define inf 0x7fffffff 11 using namespace std; 12 const int maxn=30000+10; 13 const int M = maxn*100+10; 14 15 int n,q,tot; 16 int an[maxn]; 17 int T[maxn],lson[M],rson[M],c[M]; 18 int build(int l,int r) 19 { 20 int root=tot++; 21 c[root]=0; 22 if (l!=r) 23 { 24 int mid=(l+r)>>1; 25 lson[root]=build(l,mid); 26 rson[root]=build(mid+1,r); 27 } 28 return root; 29 } 30 int update(int root,int pos,int val) 31 { 32 int newroot=tot++,tmp=newroot; 33 c[newroot]=c[root]+val; 34 int l=1,r=n; 35 while (l<r) 36 { 37 int mid=(l+r)>>1; 38 if (pos<=mid) 39 { 40 lson[newroot]=tot++ ;rson[newroot]=rson[root]; 41 newroot=lson[newroot] ;root=lson[root]; 42 r=mid; 43 } 44 else 45 { 46 rson[newroot]=tot++ ;lson[newroot]=lson[root]; 47 newroot=rson[newroot] ;root=rson[root]; 48 l=mid+1; 49 } 50 c[newroot]=c[root]+val; 51 } 52 return tmp; 53 } 54 int query(int root,int pos) 55 { 56 int ret=0; 57 int l=1,r=n; 58 while (pos<r) 59 { 60 int mid=(l+r)>>1; 61 if (pos<=mid) {r=mid ;root=lson[root] ;} 62 else {ret += c[lson[root] ] ;root=rson[root] ;l=mid+1 ;} 63 } 64 return ret+c[root]; 65 } 66 int main() 67 { 68 while (scanf("%d",&n)!=EOF) 69 { 70 tot=0; 71 for (int i=1 ;i<=n ;i++) scanf("%d",&an[i]); 72 T[n+1]=build(1,n); 73 map<int,int> mp; 74 mp.clear(); 75 for (int i=n ;i>=1 ;i--) 76 { 77 if (mp.find(an[i])==mp.end()) 78 T[i]=update(T[i+1],i,1); 79 else 80 { 81 int tmp=update(T[i+1],mp[an[i] ],-1); 82 T[i]=update(tmp,i,1); 83 } 84 mp[an[i] ]=i; 85 } 86 scanf("%d",&q); 87 while (q--) 88 { 89 int l,r; 90 scanf("%d%d",&l,&r); 91 printf("%d\n",query(T[l],r)); 92 } 93 } 94 return 0; 95 }