您的位置:首页 > 其它

光荣的梦想(逆序对模板)

2017-10-12 15:35 246 查看
<讲解链接>

一.树状数组实现

1.什么是树状数组

http://www.cnblogs.com/hsd-/p/6139376.html

2.什么是逆序对及如何实现算法

http://www.cnblogs.com/xiongmao-cpp/p/5043340.html

二.归并排序实现

1.什么是归并排序

http://blog.csdn.net/tmylzq187/article/details/51816084

2.如何实现算法

http://blog.csdn.net/Sugar_Z_/article/details/48213537

<~板子~>

题目描述:

Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。

一串数列即表示一个世界的状态。

平衡是指这串数列以升序排列,而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有序。

输入格式:

第一行为数列中数的个数 N(n≤100000)。

第二行为 N 个数 a1~an (每个数小于100000),表示当前数列的状态。

输出格式:

输出一个整数,表示最少需要交换几次能达到平衡状态。

样例数据 1

输入

4

2 1 4 3

输出:

2

备注:

本题另外一种描述:

给定一个序列 a1,a2,…,an,如果存在 i小于j 并且 ai>aj ,那么我们称之为逆序对,求逆序对的数目。

代码:

一.树状数组实现 (O(n*log(n)))

#include<bits/stdc++.h>
using namespace std;

int n,k;
int c[100005];
long long ans=0,s;

int main()
{
cin>>n;

for(int i=1;i<=n;++i)
{
cin>>k;

for(int j=k;j<100005;j+=(-j)&j)
c[j]+=1;

for(s=0;k>0;k-=(-k)&k)             //s为在ai前面且小于等于ai的元素个数。
s+=c[k];

ans+=i-s;                         //i-s为在ai前面且大于ai的元素个数
}

cout<<ans<<endl;

return 0;
}


二.归并排序实现 (O(n*log(n)))

#include<bits/stdc++.h>
using namespace std;

const int N=100005;

int n;
int a
,r
;                      //a是待排序数组,r是临时数组
long long sum=0;

inline void merge(int s,int mid,int t)
{
int k=s;
int i=s;
int j=mid+1;

while(i<=mid&&j<=t)            //二个子序列从小到大合并,直到有一列结束
if(a[i]>a[j])
{
r[k++]=a[j++];
sum=sum+(mid-i+1);
9d9d
//a[i],a[i+1],...a[mid]这一段都满足a[i]>a[j],共有mid-i+1个逆序对
}
else
r[k++]=a[i++];

while(i<=mid) r[k++]=a[i++];   //把左边子序列剩余的元素接入进来
while(j<=t)   r[k++]=a[j++];   //把右边子序列剩余的元素接入进来

for(i=s;i<=t;++i)
a[i]=r[i];                 //把合并后的有序数据重新放回a数组
}

inline void mergesort(int s,int t) //对[s,t]区间的无序数据进行归并排序
{
if(s<t)
{
int mid=(s+t)/2;           //取区间的中点

mergesort(s, mid);         //以中点二分,对左边子区间进行排序
mergesort(mid+1 ,t);       //以中点二分,对右边子区间进行排序
merge(s,mid,t);            //合并操作
}
}

int main()
{
cin>>n;

for(int i=1;i<=n;++i)
cin>>a[i];

mergesort(1,n);
cout<<sum<<endl;              //输出逆序对数量

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: