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 }

 

posted @ 2015-03-28 22:15  huangxf  阅读(287)  评论(0编辑  收藏  举报