SPOJ 3267. D-query (主席树)

A - D-query
Time Limit:1500MS     Memory Limit:0KB     64bit IO Format:%lld & %llu

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.

Example

Input 5
1 1 2 1 3
3
1 5
2 4
3 5 Output 3
2
3 

 (其实我觉得这道题作为主席树入门比第k大数要好很多)

大概就是从前往后,插入一个数则新建一棵树,如果之前没有出现,直接插入,如果之前出现了 ,再建一棵树删除,大概是这样。

(我说新建一棵树不是真的新建诶,学了主席树应该大概知道我的意思)

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int N = 30000 + 11 ;
 5 
 6 int n,a[N],li[N],q,tot,cnt,root[N],pos[N];
 7 struct id
 8 {
 9     int l,r,sum;
10 }tree[N*40];
11 
12 
13 void Init()
14 {
15     scanf("%d",&n);
16     for(int i = 1; i <= n; ++i) 
17     {
18         scanf("%d",a + i);
19         li[i] = a[i];
20     }
21     sort(li+1,li+1+n);
22     tot = 1 ;
23     for(int i = 2 ; i <= n; ++i) if( li[i] != li[tot] ) li[++tot] = li[i];        
24 }
25 
26 int binary_search( int num )
27 {
28     int l = 1 , r = tot;
29     while( l <= r )
30     {
31         int mid = l + ((r-l)>>1);
32         if(li[mid] == num) return mid;
33         if(li[mid] < num) l = mid + 1;
34         else r = mid - 1;
35     } 
36     return -1;
37 }
38 
39 void updata(int l,int r,int &x,int y,int posi,int add)
40 {
41     tree[++cnt] = tree[y] ; x = cnt; tree[cnt].sum += add;
42     if(l == r) return ;
43     int mid = l + ((r-l)>>1);
44     if(posi <= mid) updata(l,mid,tree[x].l,tree[y].l,posi,add);
45     else updata(mid+1,r,tree[x].r,tree[y].r,posi,add);
46 }
47 
48 int query( int num,int L,int R,int l,int r )
49 {
50     if(L ==l && R == r) return tree[num].sum; 
51     int mid = L + ((R-L)>>1);
52     if(r <= mid) return query(tree[num].l,L,mid,l,r);
53     else if(l > mid) return query(tree[num].r,mid+1,R,l,r);
54     else return query(tree[num].l,L,mid,l,mid) + query(tree[num].r,mid+1,R,mid+1,r);
55 }
56 
57 void Solve( )
58 {
59     for(int i = 1 ; i <= n; ++i)
60     {
61         int num = binary_search(a[i]);
62         updata(1,n,root[i],root[i-1],i,1);
63         if( pos[num] ) updata(1,n,root[i],root[i],pos[num],-1);
64         pos[num] = i;
65     }
66     scanf("%d",&q);
67     for(int i = 1 ; i <= q; ++i)
68     {
69         int l, r;
70         scanf("%d%d",&l,&r);
71         printf("%d
",query(root[r],1,n,l,r));
72     }
73 }
74 
75 int main( )
76 {
77 //    freopen("spoj3267.in","r",stdin);
78 //    freopen("spoj3267.out","w",stdout);
79     Init();
80     Solve();
81     fclose(stdin);
82     fclose(stdout);
83     return 0;
84 }
原文地址:https://www.cnblogs.com/Ateisti/p/6366370.html