zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    剑指 Offer 26. 树的子结构
    99. 恢复二叉搜索树(困难)
    93. 复原IP地址
    剑指 Offer 20. 表示数值的字符串
    100. 相同的树
    336. 回文对
    12. 整数转罗马数字(贪心!)
    块链技术在数据中心应用的成与败
    新型大脑启发式学习方法来了,可帮助人工神经网络节省内存和能量
    混合多云为何具有技术优势
  • 原文地址:https://www.cnblogs.com/Ateisti/p/6366370.html
Copyright © 2011-2022 走看看