【CSP2019准备】洛谷-P1966 火柴排队+洛谷-P1908 逆序对

P1966火柴排队
P1908逆序对

火柴排队

显然我们要让a中第i小的对应b中第i小的,粗略想一下,如果一个是2,3,一个是3,4。那么2,3对应3,4比2,3对应4,3来的更好,因为题目中的高度不同,而我们的例子是差最小的极端例子,所以可以得出结论成立。
那么问题来了,怎么一一对应。
先把a,b离散化(打上序号排序),然后根据a序号的顺序排b的序号,此时b的序号,设为数组c,c[i]表示b中c[i]位应该在第i位上,那么只要求c的逆序对即可。

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
using namespace std;
const int maxn=500005;
const ll modn=99999997;
pii a[maxn],in[3][maxn];
int n;
ll ans;
ll c[maxn];
inline int lowbit(int k)
{
	return (k&(-k));
}
void add(int i)
{
	while(i<=n)
	{
		c[i]++;
		c[i]=c[i];
		i+=lowbit(i);
	}
}
ll getsum(int i)
{
	ll sum=0;
	while(i>0)
	{
		sum+=c[i];
		sum=sum;
		i-=lowbit(i);
	}
	return sum;
}
bool cmp(pii a,pii b)
{
	return a.se<b.se;
}
int main()
{
//	freopen("testdata (2).in","r",stdin);
	scanf("%d",&n);
	rep(i,1,n) scanf("%d",&in[1][i].fi),in[1][i].se=i;
	rep(i,1,n) scanf("%d",&in[2][i].fi),in[2][i].se=i;
	ll ans=0;
	sort(in[1]+1,in[1]+n+1);sort(in[2]+1,in[2]+n+1);
	rep(i,1,n)
	{
		a[in[1][i].se].fi=in[2][i].se;
		a[i].se=i;
	}
	sort(a+1,a+n+1);
	rep(i,1,n)
	{
		add(a[i].se);
		ans+=i-getsum(a[i].se);
	}
	printf("%lld",ans%modn);
	return 0;
}

前置知识:逆序对

只会树状数组求逆序对,想法很简单,将数组离散化之后,从小到大做一个pair带着原来的位置排序,然后再从小到大把数组插回原来的位置,统计已经有多少个数字在他前面查过了,那么剩余没插的就是对于这个数的逆序数量,求和即可。

	#include<bits/stdc++.h>
	#define rep(i,k,n) for(int i=k;i<=n;i++)
	#define pii pair<int,int>
	#define fi first
	#define se second
	#define ll long long
	using namespace std;
	const int maxn=500005;
	pii a[maxn];
	int n;
	ll ans;
	ll c[maxn];
	inline int lowbit(int k)
	{
		return (k&(-k));
	}
	void add(int i)
	{
		while(i<=n)
		{
			c[i]++;
			i+=lowbit(i);
		}
	}
	ll getsum(int i)
	{
		ll sum=0;
		while(i>0)
		{
			sum+=c[i];
			i-=lowbit(i);
		}
		return sum;
	}
	int main()
	{
		scanf("%d",&n);
		rep(i,1,n)
		{
			scanf("%d",&a[i].fi);
			a[i].se=i;
		}
		sort(a+1,a+n+1);
		rep(i,1,n)
		{
			add(a[i].se);
			ans+=i-getsum(a[i].se);
		}
		printf("%lld",ans);
		return 0;
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章