• 【BZOJ 1878】 HH的项链


     【题目链接】

                https://www.lydsy.com/JudgeOnline/problem.php?id=1878

    【算法】

               显然,在线算法是不可做的,考虑离线算法

               笔者的做法是莫队算法,时间复杂度 : O(nsqrt(n))(sqrt表示开方)

               但是,树状数组的效率更高,下面讲一讲这种高效的做法 :

               不妨将所有询问按右端点排序

               对于每次询问,我们只考虑每种颜色最后出现的一次,用树状数组维护每一个位置是否对答案产生“贡献“

               具体来说,我们用一个Next数组记录这种颜色上次出现的位置,然后,对于每个位置i,如果存在Next[i],将树状数组中的Next[i]减1,将这个位置加1即可

               时间复杂度 :O(nlog(n))

     【代码】

                我的代码(莫队) :

                

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 50010
    #define MAXS 1000010
    #define MAXM 200010
    
    struct Query
    {
        int l,r;
        int id;
    } q[MAXM],b[MAXM];
    
    int i,j,k,n,m,block,len,t,sum,l,r;
    int a[MAXN],s[MAXS],ans[MAXM];
    
    inline bool cmp1(Query a,Query b)
    {
        return a.l < b.l;
    }
    inline bool cmp2(Query a,Query b)
    {
        return a.r < b.r;
    } 
    inline void add(int l,int r,int val)
    {
        int i;
        for (i = l; i <= r; i++)
        {
            if (s[a[i]] == 1 && val == -1) sum--;
            if (s[a[i]] == 0 && val == 1) sum++;
            s[a[i]] += val; 
        }        
    }
    
    int main()
    {
        
        scanf("%d",&n);
        for (i = 1; i <= n; i++) scanf("%d",&a[i]);
        scanf("%d",&m);
        for (i = 1; i <= m; i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id = i;        
        }
        sort(q+1,q+m+1,cmp1);
        len = (int)sqrt(n);
        block = n / len + (n % len != 0);
        j = 1;
        for (i = 1; i <= block; i++)
        {
            t = 0;
            sum = 0;
            while (j <= m && q[j].l > (i - 1) * len && q[j].l <= i * len) 
            {
                b[++t] = q[j];
                j++;
            }    
            sort(b+1,b+t+1,cmp2);
            l = b[1].l; r = b[1].l - 1;
            for (k = 1; k <= t; k++)
            {
                if (l < b[k].l) add(l,b[k].l-1,-1);
                else if (l > b[k].l) add(b[k].l,l-1,1);
                add(r+1,b[k].r,1);
                ans[b[k].id] = sum;
                l = b[k].l; r = b[k].r;
            }    
            add(l,r,-1);    
        }
        for (i = 1; i <= m; i++) printf("%d
    ",ans[i]);
    
        return 0;
    }

    黄学长的代码(树状数组)

    (http://hzwer.com/3007.html)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int n,m,mx;
    int a[50005],next[50005],t[50005];
    int p[1000005];
    struct data{int l,r,id,ans;}q[200005];
    bool cmp1(data a,data b)
    {return a.l==b.l?a.r<b.r:a.l<b.l;}
    bool cmp2(data a,data b)
    {return a.id<b.id;}
    int lowbit(int x){return x&(-x);}
    void update(int x,int v)
    {
        for(int i=x;i<=n;i+=lowbit(i))
            t[i]+=v;
    }
    int ask(int x)
    {
        int tmp=0;
        for(int i=x;i>0;i-=lowbit(i))
            tmp+=t[i];
        return tmp;
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read(),mx=max(mx,a[i]);
        for(int i=n;i>0;i--)
            next[i]=p[a[i]],p[a[i]]=i;
        for(int i=1;i<=mx;i++)
            if(p[i])update(p[i],1);
        m=read();
        for(int i=1;i<=m;i++)
            q[i].l=read(),q[i].r=read(),q[i].id=i;
        sort(q+1,q+m+1,cmp1);
        int l=1;
        for(int i=1;i<=m;i++)
        {
            while(l<q[i].l)
            {
                if(next[l])update(next[l],1);
                l++;
            }
            q[i].ans=ask(q[i].r)-ask(q[i].l-1);
        }
        sort(q+1,q+m+1,cmp2);
        for(int i=1;i<=m;i++)
            printf("%d
    ",q[i].ans);
        return 0;
    }
  • 相关阅读:
    BZOJ 4059 [Cerc2012]Non-boring sequences(启发式分治)
    牛客练习赛1 A
    2018年全国多校算法寒假训练营练习比赛(第一场)J
    2018年全国多校算法寒假训练营练习比赛(第一场)C
    2018年全国多校算法寒假训练营练习比赛(第一场)D
    2018年全国多校算法寒假训练营练习比赛(第一场)E
    Wannafly挑战赛7 E
    Wannafly挑战赛7 C
    Wannafly挑战赛7 B
    Wannafly挑战赛7 D
  • 原文地址:https://www.cnblogs.com/evenbao/p/9311136.html
Copyright © 2020-2023  润新知