ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树状数组 P1908 逆序对

2020-05-04 20:07:12  阅读:245  来源: 互联网

标签:val 树状 int 18 P1908 数组 id 输入 逆序


题目

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\n", answer);
}

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

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

标签:val,树状,int,18,P1908,数组,id,输入,逆序
来源: https://www.cnblogs.com/Jason66661010/p/12827953.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有