SPOJ COWPIC

题目链接:COWPIC


题面:

E - Cow Photographs
Time Limit:177MS     Memory Limit:1572864KB     64bit IO Format:%lld & %llu

Description

Farmer John wants to take a picture of his entire herd of N (1 <= N <= 100,000) cows conveniently numbered 1..N so he can show off to his friends. 

On picture day, the cows run to form a single line in some arbitrary order with position i containing cow c_i (1 <= c_i <= N). Farmer John has his own ideas about how the cows should line up. 

FJ thinks cow i may stand only to the left of cow i+1 (for all i, 1 <= i <= N-1) and that cow N may only stand to the left of Cow 1.  Of course, no cow will stand to the left of the first (leftmost) cow in the line.

The cows are hungry for the promised post-photo dinner, so Farmer John wants to take the picture as quickly as possible. Cows are not great at following directions, so he will only choose a pair of adjacent cows and have them switch places once per minute. How quickly is Farmer John able to get them into some acceptable order? 


Consider a set of 5 cows whose initial lineup looks like this:

     Left           Right
        3  5  4  2  1

He can first swap the second pair of cows:

        3  4  5  2 1

and then swap the rightmost pair:

        3  4  5  1  2

to yield an acceptable lineup that required but two minutes of cow swapping.

Input

Line 1: A single integer: N
Lines 2..N+1: Line i+1 contains the number of the i-th cow in line: c_i

Output

Line 1: The minimum amount of time, in minutes, that it takes Farmer John to get the cows into some appropriate order.

Example

Input:
5
3
5
4
2
1

Output:
2


解题:

听了别人的思路做出来的。逆序数对就是需要移动到1 2 3.... n的次数,而不断将第1位移到最后,将其当成最大的数,减去其左边的位置数,加上总数减去其位置数再减一,便得一新值,将新值与最小值比较得最优解。(前面得逆序数对数需用归并排序,nlogn,用n^2肯定不行)。


代码:

#include <stdio.h>
#include <iostream>
using namespace std;
long long int g_nCount=0;
void mergearray(int a[], int first, int mid, int last, int temp[])
{
	int i = first, j = mid + 1;
	int m = mid,   n = last;
	int k = 0;

	while (i <= m && j <= n) 
	{
		if (a[i] < a[j])
			temp[k++] = a[i++];
		else
		{
			temp[k++] = a[j++];
			g_nCount += m - i + 1;
		}
	}

	while (i <= m)
		temp[k++] = a[i++];
	while (j <= n)
		temp[k++] = a[j++];

	for (i = 0; i < k; i++)
		a[first + i] = temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
	if (first < last)
	{
		int mid = (first + last) / 2;
		mergesort(a, first, mid, temp);    
		mergesort(a, mid + 1, last, temp); 
		mergearray(a, first, mid, last, temp); 
	}
}

bool MergeSort(int a[], int n)
{
	int *p = new int[n];
	if (p == NULL)
		return false;
	mergesort(a, 0, n - 1, p);
	return true;
}

int main()
{    

	int n;
	long long int minn;
	int store[100005],p[100005];
    cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>store[i];
	}
	for(int i=0;i<n;i++)
	{
		p[store[i]]=i;
	}
	MergeSort(store, n);
	g_nCount=g_nCount-p[1]+(n-p[1]-1);
	minn=g_nCount;
	for(int i=2;i<n;i++)
	{
		g_nCount=g_nCount-p[i]+(n-p[i]-1);
		if(g_nCount<minn)
			minn=g_nCount;
	}
	printf("%lld\n",minn);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值