专栏文章

P1908 逆序对

个人记录参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipwdg0x
此快照首次捕获于
2025/12/03 19:02
3 个月前
此快照最后确认于
2025/12/03 19:02
3 个月前
查看原文

思路

题目要求求出序列中所有的逆序对个数,可以转换为求每个数所有的逆序对个数之和,算单点贡献。

转化:

转化为取一个数,将这个数后面的所以数的个数记录,若这个数后面有小于它本身的数,那么答案加一。
这时就运用到区间查询功能了,考虑使用树状数组。

树状数组:

在树状数组中存储桶排结果,当然存是在这个数后面的桶排结果,并且加入树状数组,加入等价于区间加一。
此后查询区间 11ai1a_{i}-1 的所有值,即可得出答案。
由于本题数据较大,桶排需要离散化。

code:

CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=7e5+5;
map<int,int>mp;
int n,a[N],b[N],c[N];
int cnt;
int lowbit(int x){
	return x&(-x);
}
void add(int x){
	while(x<=n){
		c[x]+=1;
		x+=lowbit(x);
	}
}
int get(int x){
	int ans=0;
	while(x>0){
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}
signed main(){
//	freopen("P1908_11.in","r",stdin);
//	freopen("P1908.txt","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i];
	}
	sort(a+1,a+n+1);
	int len=unique(a+1,a+n+1)-a-1;
	for(int i=1;i<=len;i++){
		mp[a[i]]=i;
	}
	for(int i=n;i>=1;i--){
		add(mp[b[i]]);
		cnt+=get(mp[b[i]]-1);
		//cout<<cnt<<endl;
	}
	cout<<cnt;
    return 0;
}


评论

0 条评论,欢迎与作者交流。

正在加载评论...