树状数组求排列的逆序数

由于树状数组没有负数节点和0节点,(有些书上说有0节点,是为了方便理解树状数组而假设存在的虚拟节点,),所以当排列中有负数或0的话,先将他们按照输入顺序标号,再将其从小到大排序,然后以标号为排列查找逆序数。

原理

假设数列为 5 4 3 2 1
5前面比它本身小的数有0个
4前面比它本身小的数有1个
3前面比它本身小的数有2个
2前面比它本身小的数有3个
1前面比它本身小的数有4个
所以他的逆序数为1+2+3+4=10
如果只是单纯的暴利的话,这是一种O(n2)的做法,但是我们有一种更为方便的数据结构—-树状数组,它查询和,修改单点值的复杂度为O(logn),所以复杂度就降到了O(nlogn)。
下面提供两个代码。


排列不包含0和负数

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;

int c[100005], n;

int lowbit(int i)
{
    return i & (-i);
}

void update(int k, int x)
{
    while (k <= n)
    {
        c[k] += x;
        k += lowbit(k);
    }
}
int getsum(int k)
{
    int sum = 0;
    while (k > 0)
    {
        sum += c[k];
        k -= lowbit(k);
    }
    return sum;
}

int main()
{
    while (scanf("%d", &n) > 0)
    {
        memset(c, 0, sizeof(c));
        long long int ans = 0, t;
        for (int i = 1; i <= n; i++)
        {
            cin >> t;
            update(t, 1);
            ans += i - getsum(t);
        }
        printf("%lld\n", ans);
    }
}

排列为任意数字

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
typedef struct node
{
    int data;
    int id;
}Node;

Node arr[100005];
int c[100005], n;

int cmp(Node a, Node b)
{
    if (a.data != b.data)
        return a.data < b.data;
    return a.id < b.id;
}

int lowbit(int i)
{
    return i & (-i);
}

void update(int k, int x)
{
    while (k <= n)
    {
        c[k] += x;
        k += lowbit(k);
    }
}

long long int getsum(int k)
{
    long long int sum = 0;
    while (k > 0)
    {
        sum += c[k];
        k -= lowbit(k);
    }
    return sum;
}

int main()
{
    while (scanf("%d", &n) > 0)
    {
        memset(c, 0, sizeof(c));
        long long int ans = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &arr[i].data);
            arr[i].id = i;
        }
        sort(arr + 1, arr + n + 1, cmp);
        for (int i = 1; i <= n; i++)
        {
            update(arr[i].id, 1);
            ans += i - getsum(arr[i].id);
        }
        printf("%lld\n", ans);
    }
}
全部评论

相关推荐

06-17 00:26
门头沟学院 Java
程序员小白条:建议换下项目,智能 AI 旅游推荐平台:https://github.com/luoye6/vue3_tourism_frontend 智能 AI 校园二手交易平台:https://github.com/luoye6/vue3_trade_frontend GPT 智能图书馆:https://github.com/luoye6/Vue_BookManageSystem 选项目要选自己能掌握的,然后最好能自己拓展的,分布式这种尽量别去写,不然你只能背八股文了,另外实习的话要多投,尤其是学历不利的情况下,多找几段实习,最好公司title大一点的
无实习如何秋招上岸
点赞 评论 收藏
分享
05-29 22:11
门头沟学院 Java
Elastic90:抛开学历造假不谈,这公司的招聘需求也挺怪的,Java开发还要求你有图文识别、移动端开发和c++的经验,有点逆天了。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务