树状数组 P1908 逆序对

Posted jason66661010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组 P1908 逆序对相关的知识,希望对你有一定的参考价值。

题目

https://www.luogu.com.cn/problem/P1908

题目分析

树状数组的使用原因

可以开一个数组c[maxn],来记录前面数据的出现情况,初始化为0;当数据a出现时,就令c[a]=1。这样的话,欲求某个数a的逆序数,只需要算出在当前状态下c[a+1,maxn]中有多少个1,因为这些位置的数在a之前出现且比a大。这其实就是明显的单点更新(数据a出现时,就令c[a]=1),区间查询(c[a+1,maxn]中有多少个1)——树状数组
而getsum(c[a+1,maxn])等价于 i - getsum( c[i] ),其中 i 为当前已经插入的数的个数 getsum( c[i] )为比 c[i] 小的数的个数,i- getsum( c[i] ) 即比c[i] 大的个数, 即逆序的个数。
最后需要把所有逆序数求和,就是在插入的过程中边插入边求和.

离散化原理

输入:9 -1 18 5

输出 3.

输入之后对应的结构体就会变成这样

val:9 -1 18 5

id:  1  2  3  4

排好序之后就变成了

val :  -1 5 9 18

id:      2 4  1  3

2 4 1 3 的逆序数 也是3

这样原来是输入9,就把t[9]置为1,输入18,就把t[18]置为1,最后遍历t数组到输入数字的最大值,统计出现过的次数,如果输入一个1000000,就要遍历t数组到t【1000000】

现在使用id等价代替原数组,只需要输入元素个数的空间即可,节省了数组空间

相等元素处理

如果遇到相等的元素,就使用id(即输入的顺序)区分,这样后输入的相等元素的id大,在进行id等价转换的时候它的转换情况偏小(自己的id大了,转换后相对于自己的数大了,那么找自己前面比自己大的数就有可能结果偏小),但是前面还有一个与自己数字相等的元素,它的id是准确的,也就是最后不会影响结果

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
    long long val;
    int id;
}a[500005];
long long c[500005];
int n;
bool cmp(struct node &a, struct node&b)
{
    if (a.val == b.val)return a.id < b.id;
    return a.val < b.val;
}
int lowbit(int x)
{
    return x&(-x);
}
void update(int i, int k)
{
    while (i <= n)
    {
        c[i] += k;
        i += lowbit(i);
    }
}
long long getsum(int i)
{
    long long res = 0;
    while (i > 0)
    {
        res += c[i];
        i -= lowbit(i);
    }
    return res;
}
int main()
{
    int aa, bb, cc,dd;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &a[i].val);
        a[i].id = i;
    }
    sort(a + 1, a + n + 1, cmp);
    long long answer = 0;
    for (int i = 1; i <= n; i++)
    {
        update(a[i].id,1);
        answer += i - getsum(a[i].id);//用来存储原数第i个数的order下标是什么
    }
    printf("%lld
", answer);
}

参考:https://www.jianshu.com/p/8a4081f0ec20

https://blog.csdn.net/m0_38033475/article/details/80330157

以上是关于树状数组 P1908 逆序对的主要内容,如果未能解决你的问题,请参考以下文章

树状数组 P1908 逆序对

luogu P1908 逆序对 |树状数组

P1908 逆序对(树状数组解法)

洛谷 P1908 逆序对 Label:归并排序||树状数组

P1908 逆序对——归并算法

逆序对+离散树状数组+。。。。