咳咳,用树状数组求逆序对及例题
关于树状数组,相信大家都已经比较熟悉了。。。
那么,我们就先来砍一刀例题(嘻嘻)
输入
给出n以及n个数,求这其中的逆序对个数
PS:逆序对,就是序列中ai>aj且i<j的有序对。
输入:
6
5 4 2 6 3 1
输出:
11
n<=5*10^5
ai<=10^9
嗯。。。
这一题,很多人应该都会选择归并求逆序对吧。。。
但是,树状数组求逆序对我们也应该要掌握掌握的说。
那么,想让我们想一想,逆序对应该怎么快速求呢?
我们可以倒着枚举。
void add(int x) {for (;x<=n;x+=lowbit(x)) t[x]++;}
int total(int x) {int s=0; for (;x>0;x-=lowbit(x)) s+=t[x]; return s;}
for (int i=n;i>0;i--)
	add(c[i]),ans+=total(c[i]-1);
因为ai<=10^9,我们很容易就能想到离散化
这个离散化呢,还要小心一点就是相等的情况。
n=read();//read()为读入优化
for (int i=1;i<=n;i++) a[i]=(node){read(),i};
sort(a+1,a+n+1,cmp);c[a[1].num]=1;
for (int i=2;i<=n;i++)
{
	if (a[i].val!=a[i-1].val) tot++;
	c[a[i].num]=tot;
}
这样,我们就能简单而又容易地打出代码啦!
#include<cstdio>
#include<algorithm>
#define ll long long
#define lowbit(x) x&-x
#define N 500010
using namespace std;
struct node{ll val,num;}a[N];
ll ans=0,t[N]={0},c[N];int n,tot=1;
inline int read()
{
    int x=0,f=1; char c=getchar();
    while(c<'0' || c>'9') f=(c=='-') ? -1:f,c=getchar();
    while(c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int cmp(node x,node y) {return x.val<y.val;}
void add(int x) {for (;x<=n;x+=lowbit(x)) t[x]++;}
ll total(int x) {ll s=0; for (;x>0;x-=lowbit(x)) s+=t[x]; return s;}
int main()
{
//	freopen("nxd.in","r",stdin);
//	freopen("nxd.out","w",stdout);
	n=read();
	for (int i=1;i<=n;i++) a[i]=(node){read(),i};
	sort(a+1,a+n+1,cmp);c[a[1].num]=1;
	for (int i=2;i<=n;i++)
	{
		if (a[i].val!=a[i-1].val) tot++;
		c[a[i].num]=tot;
	}
	for (int i=n;i>0;i--)
		add(c[i]),ans+=total(c[i]-1);
	printf("%lld\n",ans);
	return 0;
}
    转载需注明出处。
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号