• 逆序对与本质不同的逆序对


    在发表文章之前,蒟蒻只会用归并排序求逆序对.在考试中遇到了求数列中逆序对与本质不同的逆序对,立刻露出爆零本质,于是学习了一下树状数组求这两个子问题.

    1.逆序对

    定义:在数列中ai>aj&&i<j,将这两个数称作逆序对.

    暴力思想:直接找这个数前面比它大的数,复杂度O(n^2)???;

    树状数组:其实就是暴力的优化,在O(n)遍历是将遍历到的点都"染色","染色"后立马查询比它小的数染色的总数,用这个数的id-sum就是它前面比它大的数,即逆序对,O(nlogn).离散后再做可针对数比较大的情况.

    ps:也可直接查它前面比它大的数,即查区间(nownum,maxnum)当前被染色个数.

    2.本质不同的逆序对

    其实就是将每个数第一次出现才染色,最后一次出现才统计逆序对.

    ps:对于每个数,最后一次数之前出现的该数的逆序对的是最后一次数统计逆序对的子集,

    第一次之后的影响都是第一次影响的重复累加.

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define R register
    #define e exit(0)
    #define ll long long
    const int maxn=5*1e5+10;
    long long n,ans1,ans2,jz=-1,a[maxn],tree[maxn],fir[maxn],endd[maxn],q[maxn];
    struct shu{
        ll v,id;
    }num[maxn];
    bool cmp(shu x,shu y)
    {
        if(x.v==y.v)
            return x.id<y.id;//注意离散判重.
        return x.v<y.v; 
    }
    inline long long fd()
    {
        long long s=1,t=0;
        char c=getchar();
        while(c<'0'||c>'9')
        {
            if(c=='-')
                s=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9')
        {
            t=t*10+c-'0';
            c=getchar();
        }
        return s*t;
    }
    long long lowbit(long long x)
    {
        return x&(-x);
    }
    void add(ll x,ll v)
    {
        while(x<=n)
        {   
            tree[x]+=v;
            x+=lowbit(x);
        }
    }
    void add1(ll x,ll v)
    {
        while(x<=jz)
        {
            tree[x]+=v;
            x+=lowbit(x);
        }
    }
    long long ask(ll x)
    {
        long long sum=0;
        while(x)
        {
            sum+=tree[x];
            x-=lowbit(x);
        }
        return sum;
    }
    int main()
    {   
        freopen("deseq.in","r",stdin);
        freopen("deseq.out","w",stdout);
        n=fd();
        for(R ll i=1;i<=n;++i)
        {
            num[i].v=fd(),num[i].id=i;
            if(!fir[num[i].v])
                fir[num[i].v]=i;
            endd[num[i].v]=i;
            jz=max(jz,num[i].v);
            q[i]=num[i].v;
        }
        sort(num+1,num+1+n,cmp);
        for(R ll i=1;i<=n;++i)
            a[num[i].id]=i;
        for(R ll i=1;i<=n;++i)
        {
            add(a[i],1);
            ans1+=i-ask(a[i]);
        }
        for(R ll i=1;i<=n;++i)
            tree[i]=0;
        for(R ll i=1;i<=n;++i)
        {
            if(fir[q[i]]==i)
                add1(q[i],1);
            if(endd[q[i]]==i)
                ans2+=ask(jz)-ask(q[i]);//其实也可以离散,但要对同数值的数处理.
        }   
        printf("%lld
    %lld",ans1,ans2);
        return 0;
    }
  • 相关阅读:
    七牛云同步脚本:qshell工具的使用
    JMS微服务架构 关于事务提交失败,自动重新提交的机制
    pve服务器内网同步时钟
    Doris 高可用集群的部署
    黑苹果(Hackintosh) 安装1:用 VMware pro 16 安装 Big Sur 11.6
    虚拟机安装 Win10 ,无法启动,报错EFI Network ... Time out
    黑苹果(Hackintosh) 问题,修改CPU数量和内存数量后,系统重启失败
    【ElasticSearch】docker安装es7.12.1,设置xpack密码
    【鉴黄】nsfw鉴黄
    【Redis】redis集群
  • 原文地址:https://www.cnblogs.com/xqysckt/p/11194890.html
Copyright © 2020-2023  润新知