首页 > 编程语言 > 详细

P1908 逆序对(细节)(树状数组解法)

时间:2020-07-03 16:13:32      阅读:41      评论:0      收藏:0      [点我收藏+]

求逆序对(树状数组)

  • 逆序对是什么呢?就是说在一个序列中,如果i<j但是\(a_i>a_j\)那么(\(a[i],a[j]\))就是一个逆序对,是无序的。
  • 通俗的说,逆序对就是就是一个数与在它后面且比他小的数组成的数对。
  • 树状数组可以用来求逆序对,是利用它能求前缀/后缀和的原理
  • 将一个1~N的数组由后向前遍历,每次遍历到\(a_i\)时,在树状数组下标为\(a_i\)的地方+1,并向后一直到N维护前缀和,遍历到\(a[i]\)时,求Q(\(a[i]-1\))即\(a[i]\)与其后面的数组成的逆序对个数
    (我写这道题主要是为了记一下离散化方法,因为洛谷上的例题用map会超时)

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=5e5+5;
int t[maxn],a[maxn],n,tot;
long long ans;
inline long long rd(){
	register int x=0,f=0;register char ch=getchar();
	while(ch<‘0‘||ch>‘9‘)f|=ch==‘-‘,ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘)x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f?-x:x;
}
void A(int x,int a){
	for(;x<=n;x+=x&-x)t[x]+=a;
}
int Q(int x){
	int ans=0;
	for(;x;x-=x&-x)ans+=t[x];
	return ans;
}
struct Node{
	int id,data;
}node[maxn];
bool cmp(Node a,Node b){
	return a.data<b.data;  
}
int main(){	
//	freopen("1.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		node[i].data=rd();
		node[i].id=i;
	}
	sort(node+1,node+1+n,cmp);//离散化
	for(int i=1;i<=n;++i){
		if(node[i].data>node[i-1].data){//赋予其小点的数,我们只需要知道其相对位置即可
			a[node[i].id]=i;
		}else a[node[i].id]=a[node[i-1].id];//处理相等情况,离散化为一个数值
	}
	for(int i=n;i>=1;--i){
		ans+=(long long)Q(a[i]-1);
		A(a[i],1);
	}
	printf("%lld\n",ans);
	return 0;
}

P1908 逆序对(细节)(树状数组解法)

原文:https://www.cnblogs.com/Lour688/p/13229554.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!