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 }

 

你可能感兴趣的:(query)