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;
}

浙公网安备 33010602011771号