zoukankan      html  css  js  c++  java
  • 逆序数 (树状数组+数组离散化)


    title: 逆序数 (树状数组+数组离散化)
    tags: [树状数组]

    描述

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

    现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。

    比如 1 3 2 的逆序数就是1。

    输入

    第一行输入一个整数T表示测试数据的组数(1<=T<=5)每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000)随后的一行共有N个整数Ai(0<=Ai<1000000000),表示数列中的所有元素。数据保证在多组测试数据中,多于10万个数的测试数据最多只有一组。

    输出

    输出该数列的逆序数输出该数列的逆序数

    分析

    这题还是用树状数组来求逆序数,但是输入的数据很多,数组是不能开这么大的。这时就要把数组离散。

    举个例子,有四个数99999999 1 123 1583 数据范围太大,而树状数组中的c数组开的范围是数据的范围,这时候就需要离散化,把四个数一次标号为1 2 3 4(即第一个数,第二个数。。。),按键值排序之后 依次为2 3 4 1(即从小到大排序为第二个数,第三个数。。。),所以,第二个数是最小的,即f[2]=1,f[3]=2,f[4]=3,f[1]=4,也就是把键值变为了1~n,相对大小还是不变的,即4  1 2 3。比如要求原来四个数的逆序数总和,现在就是求4 1 2 3的逆序数总和,大大节省了空间压力(树状数组的长度是数据范围)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int e[1000000+50];
    
    ///数组的离散化
    struct node
    {
        int id;
        int val;
    
    } a[1000000+50];
    
    bool cmp(node a,node b)
    {
        if(a.val!=b.val)//注意排序方式
            return a.val<b.val;
        return a.id<b.id;
    }
    int lowBit(int x)
    {
        return x&(-x);
    }
    int SUM(int n)
    {
        int sum=0;
        while(n>0)
        {
            sum+=e[n];
            n-=lowBit(n);//从父节点向下加
        }
        return sum;
    }
    void updata(int id,int v,int n)
    {
        while(id<=n)
        {
            e[id]+=v;
            id+=lowBit(id);//从底部向父节点更新
        }
    }
    int main()
    {
        //freopen("2.txt","r",stdin);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            long long  int sum=0;
            memset(a,0,sizeof(a));
            memset(e,0,sizeof(e));
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&a[i].val);
                a[i].id=i;
            }
            sort(a+1,a+n+1,cmp);
            for(int i=1; i<=n; i++)
            {
                updata(a[i].id+1,1,n+1);
                sum+=i-SUM(a[i].id+1);
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
     
    
  • 相关阅读:
    Asp.Net.Core 系列-中间件和依赖注入Hosting篇
    Asp.Net.Core 系列-中间件和依赖注入进阶篇
    Asp.Net.Core 系列-中间件和依赖注入基础篇
    修饰符总结
    CSS3边框border知识点
    浅谈CSS中的居中
    c#中的委托和事件
    c#基础知识复习-static
    c#基础知识复习
    Bfc的理解
  • 原文地址:https://www.cnblogs.com/dccmmtop/p/6710386.html
Copyright © 2011-2022 走看看