zoukankan      html  css  js  c++  java
  • [BZOJ1878][SDOI2009]HH的项链解题报告

    HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一
    段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一
    个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只
    好求助睿智的你,来解决这个问题。
    Input
    第一行:一个整数N,表示项链的长度。 
    第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 
    第三行:一个整数M,表示HH询问的个数。 
    接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
    N ≤ 50000,M ≤ 200000。
    Output

    M行,每行一个整数,依次表示询问对应的答案。

    Sample Input
    6
    1 2 3 4 3 5
    3
    1 2
    3 5
    2 6

    Sample Output

    2

    2

    4

    看到题目,首先确定这是区间问题。然后考虑到不满足区间加减,于是考虑变形。

    我们从左到右维护前缀和,表示在此前有多少个不同的。这个很容易用树状数组实现。

    然后考虑到我们从左到右维护时,问题不一定从左到右,但这时离线的,我们就能排序后继续做。

    维护到第i位,对于每一个r在i上的询问,它的答案等于Sr-S(l-1).

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline void read(int &x)
    {
        x=0;int f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
    }
    int N,Q,arr[500005]; 
    int tree[500005];
    int ahead[1000005];
    int ans[500005];
    struct question{
        int l,r,num;
    }que[500005];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,int p)
    {
        for(int i=p;i<=N;i+=lowbit(i))
            tree[i]+=x;
    }
    int query(int p)
    {
        int ans=0;
        for(int i=p;i>0;i-=lowbit(i))
            ans+=tree[i];
        return ans; 
    }
    bool cmp1(question a,question b)
    {
        return a.r<b.r;
    }
    bool cmp2(question a,question b)
    {
        return a.num<b.num;
    }
    int main()
    {
        read(N);
        for(int i=1;i<=N;i++)
            read(arr[i]);
        read(Q);
        for(int i=1;i<=Q;i++)
        {
            read(que[i].l);
            read(que[i].r);
            que[i].num=i;
        } 
        sort(que+1,que+Q+1,cmp1);
        int ques=1;
        for(int i=1;i<=N;i++)
        {
            if(!ahead[arr[i]]){
                ahead[arr[i]]=i;
                update(1,i);
            }
            else{
                update(-1,ahead[arr[i]]);
                update(1,i);
                ahead[arr[i]]=i;
            }
            while(ques<=Q){
                if(que[ques].r==i)
                {
                    ans[que[ques].num]=query(que[ques].r)-query(que[ques].l-1);
                    ques++;
                }        
                else
                    break;
            }
        }
        for(int i=1;i<=Q;i++)
            printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    分享一下用终端的命令来恢复丢失的硬盘分区表 (转)
    Smart Link
    underrun || overrun
    mtr命令详解诊断网络路由
    tracert traceroute
    OE1、OE2、ON1、ON2路由有什么区别?
    GRE tunnel 2
    【SAP HANA】新建账户和数据库(2)
    【SAP HANA】SAP HANA开篇(1)
    入职一周
  • 原文地址:https://www.cnblogs.com/sherrlock/p/9549694.html
Copyright © 2011-2022 走看看