zoukankan      html  css  js  c++  java
  • luogu1972 [SDOI2009] HH的项链

    题目大意

      给一段长度n(n<=100000)序列,每次询问一段区间(个数<=200000),问区间中的数字种数。

    题解

      本题特别之处在于区间内的数字种数不满足区间的相加性,所以我们可以加约束条件。我们不妨考虑维护一个树状数组维护数字种数。显然当询问的r固定时,对于每一个数值,我们只保留其在[1,r]内最右侧的数字,将其它数字删除,这样对结果没有影响,反而数字的个数满足区间可加性了。所以定义树状数组维护的前缀和值为满足约束条件——对于每个数值只保留位置最右侧的数字——时,[1,r]中仍然存在的数字的个数。

      因此,我们将所有询问按照右端点排序,当树状数组负责的右端点要向右延伸时,要在树状数组中把右端点的数值与其相等、位置位于它左侧的位置(解决的办法貌似叫做“链式前向星”?)对应前缀和更新-1,将右端点所在位置对应前缀和更新+1即可。

      一定要注意查询是排过序的,输出时要按照原有的顺序输出!!!!!

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_LEN = 500010, MAX_VAL = 1000010, MAX_QUERY = 200010;
    int OrgData[MAX_LEN], EqValPrev[MAX_LEN];
    int Len, TotQuery;
    
    struct BIT
    {
    private:
        int C[MAX_LEN];
        int N;
    
        int Lowbit(int x)
        {
            return x & -x;
        }
    
    public:
        BIT(int n):N(n){}
    
        void Update(int p, int val)
        {
            if (p == 0)
                return;
            while (p <= N)
            {
                C[p] += val;
                p += Lowbit(p);
            }
        }
    
        int Query(int p)
        {
            int ans = 0;
            while (p >= 1)
            {
                ans += C[p];
                p -= Lowbit(p);
            }
            return ans;
    
        }
    };
    
    struct Query
    {
        int L, R, Ans;
    }_qs[MAX_QUERY], *SortedQ[MAX_QUERY];
    
    bool Cmp_R(Query *a, Query *b)
    {
        return a->R < b->R;
    }
    
    void GetEqValPrev()
    {
        static int valPrev[MAX_VAL];
        for (int i = 1; i <= Len; i++)
        {
            EqValPrev[i] = valPrev[OrgData[i]];
            valPrev[OrgData[i]] = i;
        }
    }
    
    int main()
    {
        scanf("%d", &Len);
        for (int i = 1; i <= Len; i++)
            scanf("%d", OrgData + i);
        scanf("%d", &TotQuery);
        for (int i = 1; i <= TotQuery; i++)
            scanf("%d%d", &_qs[i].L, &_qs[i].R);
    
        static BIT g(Len);
        for (int i = 1; i <= TotQuery; i++)
            SortedQ[i] = _qs + i;
        sort(SortedQ + 1, SortedQ + TotQuery + 1, Cmp_R);
        GetEqValPrev();
        int curR = 0;
        for (int i = 1; i <= TotQuery; i++)
        {
            while (curR < SortedQ[i]->R)
            {
                curR++;
                g.Update(EqValPrev[curR], -1);
                g.Update(curR, 1);
            }
            SortedQ[i]->Ans = g.Query(SortedQ[i]->R) - g.Query(SortedQ[i]->L - 1);
        }
        for (int i = 1; i <= TotQuery; i++)
            printf("%d
    ", _qs[i].Ans);
        return 0;
    }
    

      

  • 相关阅读:
    WIFI:802.11无线LAN
    如何使你的PPT更高调
    windows的注册表有什么用?
    Steeltoe之Config客户端篇
    初探Spring Cloud Config
    .NET Core开发日志——ADO.NET与SQL Server
    .NET Core开发日志——Linux版本的SQL Server
    .NET Core开发日志——视图与页面
    .NET Core开发日志——Filter
    .NET Core开发日志——Model Binding
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9488711.html
Copyright © 2011-2022 走看看