spoj-D-query(主席树)

题目链接

1.思路

扫描数组,以root[i]为根的线段树上记录的是从第一个位置到i位置的数字信息,即当前线段树上的节点记录的是数组的位置信息;

2.code

 1 #include <cstdio>
 2 #include <map>
 3 using namespace std;
 4 const int N = 3e4 + 5;
 5 
 6 struct segTree {
 7     int lc, rc, cnt;
 8 };
 9 
10 segTree ret[N*20];
11 int root[N];
12 int o;
13 
14 void build(int &i, int l, int r) {
15     ret[o].cnt = 0;
16     i = o ++;
17     if(l < r) {
18         int m = (l + r) >> 1;
19         build(ret[i].lc, l, m);
20         build(ret[i].rc, m+1, r);
21     }
22 }
23 
24 int query(int rt, int pos, int k, int l, int r) {
25     if(l == r) {
26         return k + ret[rt].cnt;        //注意要加上前为值储存的数字的个数
27     }
28     int m = (l + r) >> 1;
29     if(pos <= m) {
30         //向右子树中统计,因为时统计pos之后数字的个数,所以要加上右子树所包含的数字的个数
31         return query(ret[rt].lc, pos, k+ret[ret[rt].rc].cnt, l, m);
32     }
33     else {
34         return query(ret[rt].rc, pos, k, m+1, r);
35     }
36 }
37 
38 void update(int &i, int pos, int val, int l, int r) {
39     ret[o] = ret[i];
40     ret[o].cnt += val;
41     i = o++;
42     if(l < r) {
43         int m = (l + r) >> 1;
44         if(pos <= m) {
45             update(ret[i].lc, pos, val, l, m);
46         }
47         else {
48             update(ret[i].rc, pos, val, m+1, r);
49         }
50     }
51 }
52 
53 int main(int argc, char const *argv[]) {
54     int n, m;
55     while(~scanf("%d", &n)) {
56         o = 0;
57         build(root[0], 1, n);
58         map<int, int> mp;
59         int x;
60         for(int i = 1; i <= n; ++ i) {
61             scanf("%d", &x);
62             if(mp.count(x) == 0) {
63                 update(root[i] = root[i-1], i, 1, 1, n);    //
64             }
65             else {
66                 // 将先前一次出现的x的信息删除
67                 update(root[i] = root[i-1], mp[x], -1, 1, n);
68                 update(root[i],  i, 1, 1, n);
69             }
70             mp[x] = i;    // 更新最近一次出现x的位置
71         }
72         scanf("%d", &x);
73         while(x --) {
74             int l, r;
75             scanf("%d%d", &l, &r);
76             // 统计以r为根节点的树中l之后的数字个数
77             printf("%d\n", query(root[r], l, 0, 1, n));
78         }    
79     }
80     return 0;
81 }

 



 

posted @ 2017-03-16 12:10  zq216991  阅读(190)  评论(0编辑  收藏  举报