P1774 最接近神的人_NOI导刊2010提高(02)

P1774 最接近神的人_NOI导刊2010提高(02)


关于此题为什么可以使用求逆序对的方法来做

假设一个数\(a_i\),且前\(i-1\)个数已经成为单调增的数列。

我们要从前\(a_1\)\(a_{i-1}\)个数的有序队列中插入\(a_i\)

且只能使用类似冒泡排序的方法交换。

那么,插入这个数\(a_i\)需要交换的次数就是他的逆序对数。

有如下两种\(i\)的取值情况

--- \(i==1\) \(i>1\)
逆序对数 \(0\) 可以推得

所以这种题就是求一个逆序对的个数,就\(\mathfrak{van}\)♂了

有道云markdown真难用

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	long long val;
	int pos;
};
node data[600000];
bool compare(const node &a,const node &b)
{
	return a.val>b.val;
}
int bit[600000];
int num;
void insert(int pos,int val)
{
	while(pos<=num)
	{
		bit[pos]+=val;
		pos+=pos&(-pos);
	}
	return ;
}
long long  sum(int pos)
{
	long long res=0;
	while(pos)
	{
		res+=bit[pos];
		pos-=pos&(-pos);
	}
	return res;
}
int comp[600000];
int main()
{
	int n;
	scanf("%d",&n);
	num=n;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&data[i].val);
		data[i].pos=i;
	}
	sort(data+1,data+1+n,compare);
	long long now=-(1ll<<61);
	int ha=0;
	for(int i=1;i<=n;i++)
	{
		if(data[i].val!=now)
		{
			now=data[i].val;
			ha+=1;
		}
		comp[data[i].pos]=ha;
	}
	long long ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=sum(comp[i]-1);
		insert(comp[i],1);
	}
	printf("%lld",ans);
}
posted @ 2018-06-01 21:26  Lance1ot  阅读(98)  评论(0编辑  收藏  举报