P1908 逆序对 【树状数组】

洛谷 P1908 -> Click Here

题意

\(\mathcal{Tom}\)​​ 和 \(\mathcal{Jerry}\)​​ 在 van♂游戏:找出一序列中逆序对的个数

逆序对就是序列中 \(a_i>a_j\)\(i<j\) 的有序对

思路

BIT \(=\)​ 树状数组 \(=\)​ 二进制查找树

变量解读:

\(a[i]\) :原序列第 \(i\)​ 位的数字

\(d[i]\) :原序列中第 \(i\)​ 大的数在原序列中的下标(下标从 \(1\) 开始

\(t[i]\) :树状数组

code

#include<iostream>
#include<algorithm>
#define int long long//记得开long long
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
using namespace std;
const int N = 500005;
int n,ans;
int a[N],d[N],t[N];
int read(){//需要较快的读入
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
bool cmp1(int x,int y){
	if(a[x]==a[y]) return x>y;
	return a[x]>a[y];
}
int lowbit(int x){return x&-x;}
void Add(int x){
	while(x<=n){
		t[x]++;
		x+=lowbit(x);
	}
}
int Query(int x){
	int res=0;
	while(x>=1){
		res+=t[x];
		x-=lowbit(x);
	}
	return res;
}
void solve(){
	n=read();
	REP(i,1,n){
		a[i]=read();
		d[i]=i;
	}
	sort(d+1,d+n+1,cmp1);//离散化求d[i]
	for(int i=1;i<=n;i++){
		Add(d[i]);//在树状数组中添加一个数
		ans+=Query(d[i]-1);//求大小比这个数大,但位置却比这个数靠前的数的个数
	}
	cout<<ans<<endl;
}
signed main(){
	solve();
	return 0;
}
posted @ 2021-08-08 16:51  莳曳  阅读(31)  评论(0)    收藏  举报