zoukankan      html  css  js  c++  java
  • 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
    ", query(root[r], l, 0, 1, n));
    78         }    
    79     }
    80     return 0;
    81 }


  • 相关阅读:
    js dom
    js Number string
    jq ajax数据交互
    js date 和 math
    js中英文网页切换
    日常使用
    php求和
    empty()
    时间戳、日期相互转换
    数组转字符串之间相互转换
  • 原文地址:https://www.cnblogs.com/topk/p/6580068.html
Copyright © 2011-2022 走看看