zoukankan      html  css  js  c++  java
  • SPOJ 3267 D-query (可持久化线段树,区间重复元素个数)

    D-query

    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 

    题意:
    求区间内不重复的数的个数。 n,m<=100000
    题解:建立可持久化线段树,以右端点为最后建立现在版本线段树,
       然后就是维护每一棵线段树,就是前面的点什么时候失效,询问大区间就一定会包含小区间中的
       相同权值的点,然后只需要记录和即可,离散化还是需要的+二分。
     1 #include<cstring>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdio>
     6 
     7 #define N 60007
     8 #define M 20000007
     9 using namespace std;
    10 inline int read()
    11 {
    12     int x=0,f=1;char ch=getchar();
    13     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
    14     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    15     return x*f;
    16 }
    17 
    18 int n,top,sz,q;
    19 int a[N],b[N],num[N],pos[N],root[N];
    20 int ls[M],rs[M],sum[M];
    21 
    22 int bs(int num)
    23 {
    24     int l=1,r=top;
    25     while(l<=r)
    26     {
    27         int mid=(l+r)>>1;
    28         if (b[mid]==num) return mid;
    29         if (b[mid]<num) l=mid+1;
    30         else r=mid-1;
    31     }
    32 }
    33 void change(int l,int r,int x,int &y,int wei,int z)
    34 {
    35     y=++sz;
    36     if (l==r)
    37     {
    38         sum[y]=sum[x]+z;
    39         return;
    40     }
    41     ls[y]=ls[x],rs[y]=rs[x],sum[y]=sum[x]+z;
    42     int mid=(l+r)>>1;
    43     if (wei<=mid) change(l,mid,ls[x],ls[y],wei,z);
    44     else change(mid+1,r,rs[x],rs[y],wei,z);
    45 }
    46 
    47 int query(int p,int l,int r,int x,int y)
    48 {
    49     if (l==x&&y==r) return sum[p];
    50     int mid=(l+r)>>1;
    51     if (y<=mid) return query(ls[p],l,mid,x,y);
    52     else if (x>mid) return query(rs[p],mid+1,r,x,y);
    53     else return query(ls[p],l,mid,x,mid)+query(rs[p],mid+1,r,mid+1,y);
    54 }
    55 int main()
    56 {
    57     int n=read();
    58     for (int i=1;i<=n;i++)
    59         a[i]=read(),b[i]=a[i];
    60     sort(b+1,b+n+1);
    61     top=1;
    62     for (int i=2;i<=n;i++)
    63         if (b[i]!=b[i-1]) b[++top]=b[i];
    64     for (int i=1;i<=n;i++)
    65     {
    66         int num=bs(a[i]);
    67         change(1,n,root[i-1],root[i],i,1);
    68         if (pos[num]) change(1,n,root[i],root[i],pos[num],-1);
    69         pos[num]=i;
    70     }
    71     q=read();
    72     while(q--)
    73     {
    74         int l=read(),r=read();
    75         printf("%d
    ",query(root[r],1,n,l,r));
    76     }
    77 }
     
  • 相关阅读:
    2018第九届蓝桥杯C/C++ B国赛 —— 第三题:格雷码
    数据结构和算法 —— 谈谈算法
    数据结构和算法 —— 谈谈算法
    数据结构和算法 —— 绪论
    数据结构和算法 —— 绪论
    2018第九届蓝桥杯C/C++ B国赛 —— 第二题:激光样式
    2018第九届蓝桥杯C/C++ B国赛 —— 第二题:激光样式
    2018第九届蓝桥杯C/C++ B国赛 —— 第一题:换零钞
    围棋
    恶搞造句
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8033421.html
Copyright © 2011-2022 走看看