zoukankan      html  css  js  c++  java
  • SPOJ

    题目链接: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
    ",query(T[l],r));
    92         }
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    ORACLE 11.2.0.4 OCR VOTING DISK 模拟恢复场景
    Oracle Enterprise Linux 6.4 下配置vncserver
    Oracle Enterprise Linux 6.4 下挂载ISCSI 设备
    关于Solaris 的磁盘的分区
    【Google Earth】pro之视频录制
    【爱江山越野跑】ITRA积分认证流程
    android发送邮件
    android手机有多个摄像头,打开其中一个
    Android截图
    Android中的ACCESS_MOCK_LOCATION权限使用Demo
  • 原文地址:https://www.cnblogs.com/huangxf/p/4374937.html
Copyright © 2011-2022 走看看