zoukankan      html  css  js  c++  java
  • spoj DQUERY

    DQUERY - 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
    题目大意:每次询问区间[l,r]内有多少个不同的数.
    分析:主席树的妙用!
       第i棵主席树维护的是[1,i]这个区间内,有多少个位置的数被标记了. 当出现一个数x时,如果前面没有出现过x,就直接在第i棵主席树上将位置i个标记即可. 否则就在第i棵主席树上将x之间出现过的位置的标记给清除掉,在当前位置打上标记. 这样就保证了每棵主席树维护的区间内的所有的数最多被标记一次. 那么就可以根据这来进行统计.
       查询则类似线段树. 从[1,n]这个区间查起. 每次查当前区间内有哪些位置被标记了.当要查询[l,r]时,在第r棵主席树上查,因为它记录的是[1,r]的信息,为了保证所求的答案都在左端点的右边,每次都要对查询的区间进行判断.看是不是在左端点右边.
       这道题有点像bzoj2653.换了维护的东西. 挺神奇的.
       坑点:清除以前的标记打上现在的标记时,要以第i棵主席树为基础来建树,不要以第i-1棵主席树为基础!
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 30010;
    int n,root[maxn],pos[1000010],tot,Q;
    
    struct node
    {
        int left,right,sum;
    }e[maxn * 40];
    
    void build(int &o,int l,int r)
    {
        o = ++tot;
        e[o].sum = 0;
        if (l == r)
        {
            e[o].left = e[o].right = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(e[o].left,l,mid);
        build(e[o].right,mid + 1,r);
    }
    
    void update(int l,int r,int x,int &y,int poss,int v)
    {
        e[y = ++tot] = e[x];
        e[y].sum += v;
        if (l == r)
            return;
        int mid = (l + r) >> 1;
        if (poss <= mid)
            update(l,mid,e[x].left,e[y].left,poss,v);
        else
            update(mid + 1,r,e[x].right,e[y].right,poss,v);
    }
    
    int query(int x,int y,int l,int r)
    {
        if (l == r)
            return e[y].sum;
        int mid = (l + r) >> 1;
        if (mid >= x)
            return e[e[y].right].sum + query(x,e[y].left,l,mid);
        else
            return query(x,e[y].right,mid + 1,r);
    }
    
    int main()
    {
        scanf("%d",&n);
        build(root[0],1,n);
        for (int i = 1; i <= n; i++)
        {
            int x;
            scanf("%d",&x);
            if (!pos[x])
            {
                pos[x] = i;
                update(1,n,root[i - 1],root[i],i,1);
            }
            else
            {
                update(1,n,root[i - 1],root[i],pos[x],-1);
                pos[x] = i;
                update(1,n,root[i],root[i],i,1);
            }
        }
        scanf("%d",&Q);
        while (Q--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(l,root[r],1,n));
        }
    
        return 0;
    }

       
  • 相关阅读:
    【Hadoop报错】The directory item limit is exceeded: limit=1048576 items=1048576
    【Error】mysql的error.log中ranges: 268 max_threads: 4 split: 268 depth: 2是什么意思?
    【Hadoop】Hadoop集群组件默认端口
    【Python】用Python把从mysql统计的结果数据转成表格形式的图片并推送到钉钉群
    微信小程序 服务端shiro用户验证,偶然会出现验证失败的问题。
    微信小程序 数组复制 改变原数组 新数组也会自动变化
    Controller 在加入aop 后,@Autowired注入值为null
    gitblit仓库
    mybatis plus 增加数据后 返回主键id
    Shiro 访问 Swagger2报404 及 放行Swagger2
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8721489.html
Copyright © 2011-2022 走看看