• Tido 习题-二叉树-树状数组求逆序对


    这里给大家提供一个全新的求逆序对的方法

    是通过树状数组来实现的

    题目描述

     
     


    样例输入 Copy

    5
    2 3 1 5 4

    样例输出 Copy

    3

    提示

     
     
     
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<string>
    #include<cstring>
    using namespace std;
    struct lisan{
        long long val,index;
    };
    lisan a[100005];
    long long C[100005];
    int nn;
    int cmp1(lisan a,lisan b){
        if(a.val==b.val)return a.index<b.index;//sort的不稳定性
    //因为再下一次是按照下标再排回来,所以如果有数值相等的数,原来的下标先后顺序不能改变,否则会出现一些玄学错误
    return a.val<b.val; } int cmp2(lisan a,lisan b){ return a.index<b.index; } int lowbit(int x){ return x&(-x); } void add(int x,int d){ while(x<=nn){ C[x]+=d; x+=lowbit(x); }//修改是从左往右 } long long sum(int x){ long long ret=0; while(x>0){ ret+=C[x]; x-=lowbit(x);//求和是从右往左 } return ret; } int main() { int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].val; a[i].index=i; } //数据离散化模式开始 sort(a+1,a+n+1,cmp1); int x=0; for(int i=1;i<=n;i++){ if(a[i].val==a[i-1].val) a[i].val=x; else a[i].val=++x; } nn=x; sort(a+1,a+n+1,cmp2); //开始前缀和 long long ans=0; for(int i=n;i>=1;i--){ add(a[i].val,1); ans+=sum(a[i].val-1); } cout<<ans; return 0; }
    思路讲解:
    假如有8个数,
    a:1 3 2 4 3 1 2 4
    从后往前扫
    设一个数组分别表示从后往前扫当前每个数值一共出现了几次
    一开始是这样的,扫最后一个4
    b:0 0 0 1
    b[4]之前全是0,所以ans=0+0+0 这里的前缀和用树状数组就可以
    再扫2
    b:0 1 0 1       b[2]之前全是0
    再扫1
    b:1 1 0 1     b[1]之前还是0
    再扫3
    1 1 1 1     终于b[3]之前1+1=2意思也就是之前的两个1,代表已经扫过的1、2分别出现了一次
    也就是说,在a数组中,a[5]后比3小的一共有两个
    如此往下。。。。。
    但是这一题每一个数的最大值是10的九次方,要是开数组的话就炸了
    但是数的个数最多只有100000
    所以可用数据离散化
    先从小到大排序
    都压成1,2,3.。。。
     
     
    至于数据离散化是什么呢
    就是比如原来有一组数1 2 45 67568684 3252 653357.
    因为数据范围较大,但是数的个数却不是很大
    但是如果有的数太大有的数太小
    就会不是非常方便
    这样如果用这个数的数值作为一个数组的下标,当然就方便多了
    我们在使用的时候只看重数与数之间谁大谁小的关系
    可以把上面的一行数缩成1 2 3 6 4 5
  • 相关阅读:
    ServU使用方法及应用技巧
    Mozilla公布火狐4详情:更快 更支持开放标准
    FastReport4.6程序员手册_翻译 转
    Delphi调用C写的dll
    动态创建Fastreport
    字符串通用类
    去除全角半角字符
    系统运行的命令集锦
    打印机的大小设置
    旋转字体的设置
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/10887694.html
Copyright © 2020-2023  润新知