蒟蒻40分代码求助

P1908 逆序对

liuyuhanyyds @ 2021-11-03 18:27:46

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+7;
struct lyh
{
    long long num,id;
}a[maxn];
long long n,ls[maxn],tree[maxn],ans=0;
bool cmp(lyh x,lyh y)
{
    return x.num<y.num;
}
long long lowbit(long long x)
{
    return x&(-x);
}
void updata(long long i,long long k)
{
    while(i<=n)
    {
        tree[i]+=k;
        i+=lowbit(i);
    }
}
long long getsum(long long i)
{
    long long res=0;
    while(i>0)
    {
        res+=tree[i];
        i-=lowbit(i);
    }
    return res;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)   cin>>a[i].num,a[i].id=i;
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)   ls[a[i].id]=i;
    for(int i=1;i<=n;i++)
    {
        updata(ls[i],1);
        ans+=(i-getsum(ls[i]));
    }
    cout<<ans;
    return 0;
}

by loris @ 2021-11-03 18:32:56

你这做法也是够奇葩


by loris @ 2021-11-03 18:35:03

树状数组求逆序对不需要排序
求逆序对,就是求在对于没个i,a[1~i-1]中比a[i]大的数的个数的总和。

显然一个简单的处理方法就是每次让b[a[i]]+1,然后找b[1~i-1]的和就代表在a[1~i-1]中比a[i]小的数的个数,一减就可以得到比a[i]大的个数。

这个过程就可以用树状数组维护。


by xixike @ 2021-11-03 18:46:31

@loris 树状数组求逆序对排序不是很正常吗?排序之后插入查询离散化之后的排名也很好理解吧


by xixike @ 2021-11-03 19:10:29

@liuyuhanyyds 你排序之后再给ls数组赋值其实相当于对原数组离散化(意思就是没排序)。 问题出在排序上,直接sort是不稳定的,意思是两个相等的数排序之后可能会交换位置,而在这道题中交换位置会有影响,所以sort要这么写:

if(x.num != y.num) return x.num < y.num;
return x.id < y.id;

by xixike @ 2021-11-03 19:11:08

cmp 里,打错了/kk。


by loris @ 2021-11-03 19:25:53

@xixike 啊我之前一直都是离散化但不排序啊又学到了新做法


by liuyuhanyyds @ 2021-11-04 18:16:15

@xixike 谢谢神犇,已经改好了


|