利用树状数组求逆序对(模板题)

本文介绍了一道洛谷题目,通过C++实现,使用树状数组的方法计算序列中逆序对的数量。首先对数据进行离散化处理,然后提供两种遍历方式求解,并给出了两道巩固树状数组知识点的练习题目。
摘要由CSDN通过智能技术生成

来自洛谷的模板题  题目链接

题目意思即求序列中逆序对的数目

通过ac代码来供大家学习

#include<bits/stdc++.h>
#define lowbit(x)  ((x)&- (x))
using namespace std;
const int N=501000;
long long a[N],b[N];
long long tree[N];
void add(int x,int y)//添加数据
{
	while(x<=N)
	{
		tree[x]+=y;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=tree[x];
		x-=lowbit(x);
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	long long n,i;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=a[i];
	}
    //以下进行数据离散化,目的是为了缩短tree的空间,便于快速查找
	sort(a+1,a+1+n); //先将数组排序
	int cnt=unique(a+1,a+1+n)-a; //将数组去重,记录去重后数组的长度
	for(i=1;i<=n;i++)
	{
		b[i]=lower_bound(a+1,a+1+cnt,b[i])-a; //b此时是原数组,在a数组中查看当前值排序的位置
	}                                                                     //赋给b数组
    // 此时b数组已是离散好的数组                         
	long long ans=0;
    //以下展示两种遍历求逆序对个数的方法
	for(i=n;i>=1;i--) //倒序求
	{
		ans+=sum(b[i]-1);//计算比tree数组中此时值比该值小的的数目有多少
		add(b[i],1); //将该点加入tree数组
	}
//	for(i=1;i<=n;i++)//正序求
//	{
//		ans+=sum(N)-sum(b[i]); //计算比tree数组中此时值比该值大的的数目有多少
//		add(b[i],1);
//	}
	cout<<ans<<'\n';
    return 0;
}

洛谷 P5200  Sleepy Cow Sorting G

加更,附带一个关于树状数组的好题(链接如下)

[USACO19JAN] Sleepy Cow Sorting G - 洛谷

附我的ac代码

#include<bits/stdc++.h>
#define lowbit(x) ((x) &- (x));
using namespace std;
int n;
int tree[500009];
int a[500009];
void add (int x,int d)
{
	while(x<=n)
	{
		tree[x]+=d;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int ans=0;
	while(x>0)
	{
		ans+=tree[x];
		x-=lowbit(x);
	}
	return ans;
}
int main ()
{
	int i,pos=0;
	cin>>n;
	for(i=1;i<=n;i++)
		cin>>a[i];
	for(i=n-1;i>=1;i--)
	{
		if (a[i]>a[i+1])
		{
			pos=i;
			break;
		}
	}
	cout<<pos<<'\n';
	if (pos==0)
		return 0;
	for(i=pos+1;i<=n;i++)
		add(a[i],1);
	for(i=1;i<=pos;i++)
	{
		cout<<pos-i+sum(a[i])<<" ";
		add(a[i],1);
	}
	return 0;
}

acwing 242. 一个简单的整数问题

acwing 243. 一个简单的整数问题2

可以写这两道题巩固树状数组这个知识点哈

如有错误,虚心请教

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值