树状数组求逆序对

离散化(不去重)
2 33423434 437834 25345 373 35  //将上面的数字换成下边的
1    6       5      4    3   2
之后再通过楼兰图腾中的思想求逆序对
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef pair<int,int>PII;
typedef long long ll;
const int N=5e5+10;

PII a[N];
int b[N],c[N],n;

int ask(int x)
{
    int sum=0;
    for(;x>=1;x-=x&-x)
        sum+=c[x];
    return sum;
}

void add(int x,int k)
{
    for(;x<=n;x+=x&-x)
        c[x]+=k;
}

int main()
{
//    freopen("P1908_11.in","r",stdin);
    cin>>n;
    ll sum=0;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].first),a[i].second=i;
    sort(a+1,a+n+1);
    int cnt=0;
    a[0].first=-1;
    for(int i=1;i<=n;i++)
    {
        if(a[i].first==a[i-1].first)
            b[a[i].second]=cnt;
        else
        {
            b[a[i].second]=++cnt;
        }
    }
    //两种思路,倒序扫就是扫b[i]之后比b[i]小的数的个数
        for(int i=n;i>=1;i--)
	{
		sum+=ask(b[i]-1);
		add(b[i],1);	
	} 
    //正序扫就是求比b[i]之前比b[i]大的数的个数
    for(int i=1;i<=n;i++)
    {
        sum+=ask(n)-ask(b[i]);
        // cout<<cnt<<endl;
        add(b[i],1);
    }
    cout<<sum;
}
posted @ 2021-02-03 23:27  30天CF上蓝!!!  阅读(45)  评论(0编辑  收藏  举报