zoukankan      html  css  js  c++  java
  • BZOJ 1878: [SDOI2009]HH的项链

    题目描述

    num[i]表示在[l,r]内数字i的个数 

    当区间变为[l±1,r]或,[l,r±1]的时候,num[i]由0变为1或由1变为0时答案才会变化 

    #include<complex>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=5e4+7;
    struct node{
        int l,r,id;
    }q[N<<2];
    int n,m;
    int ans[N<<2],a[N],num[N*20],pos[N];
    int qread()
    {
        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;
    }
    bool cmp(const node &a,const node &b)
    {
        if(pos[a.l]==pos[b.l])return a.r<b.r;
        return pos[a.l]<pos[b.l];
    }
    void change(int &tot,int id,int add)
    {
        if(add)
        {
            if(!num[a[id]])
                tot++;
            num[a[id]]++;
            return;
        }
        num[a[id]]--;
        if(!num[a[id]])tot--;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            a[i]=qread();
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            q[i].l=qread();q[i].r=qread();
            q[i].id=i;
        }
        int tmp=sqrt(n);
        for(int i=1;i<=n;i++)
            pos[i]=(i-1)/tmp+1;
        sort(q+1,q+m+1,cmp);
        int l=1,r=0,tot=0;
        for(int i=1;i<=m;i++)
        {
            while(l<q[i].l)
                change(tot,l++,0);
            while(l>q[i].l)
                change(tot,--l,1);
            while(r<q[i].r)
                change(tot,++r,1);
            while(r>q[i].r)
                change(tot,r--,0);
            ans[q[i].id]=tot;
        }
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    莫队

    也可以用离线算法+树状数组来做这道题

    用nxt[i]来记录下一个与第i个数相同的数的位置

    将询问的区间按左端点进行排序

    用一个指针l指向当前区间的左端点,当l向右移动时,第l个数就不在查询的区间内了,这时就将树状数组中nxt[l]位置上的数+1(自己举个例子就比较好理解了)

    #include<complex>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=5e4+7;
    struct node{
        int l,r,id;
    }q[N<<2];
    int n,m;
    int c[N],nxt[N],pre[N*20],ans[N<<2];
    int qread()
    {
        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;
    }
    inline int Lowbit(int x)
    {
        return x&-x;
    }
    inline int Add(int x,int v)
    {
        for(;x<=n;x+=Lowbit(x))
            c[x]+=v;
    }
    inline int Sum(int x)
    {
        int ans=0;
        for(;x;x-=Lowbit(x))
            ans+=c[x];
        return ans;
    }
    bool cmp(const node &a,const node &b)
    {
        return a.l<b.l;
    }
    int main()
    {
        scanf("%d",&n);
        int x;
        for(int i=1;i<=n;i++)
        {
            x=qread();
            nxt[pre[x]]=i;
            if(!pre[x])Add(i,1);
            pre[x]=i;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            q[i].l=qread();q[i].r=qread();
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp);
        int l=1;
        for(int i=1;i<=m;i++)
        {
            while(l<q[i].l)
            {
                if(nxt[l])
                    Add(nxt[l],1);
                l++;
            }
            ans[q[i].id]=Sum(q[i].r)-Sum(q[i].l-1);
        }
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    树状数组
  • 相关阅读:
    Redis源代码分析(十三)--- redis-benchmark性能測试
    kvm中运行kvm
    umount.nfs device busy day virsh extend diskSpace, attachDisk
    ultravnc
    openNebula dubug
    maintenance ShellScripts
    virsh VMI deploy data serial xml
    cloud computing platform,virtual authentication encryption
    基于C 的libvirt 接口调用
    storage theory
  • 原文地址:https://www.cnblogs.com/LeTri/p/8575126.html
Copyright © 2011-2022 走看看