集训队专题(9)1003 Frosh Week

Frosh Week

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2565    Accepted Submission(s): 851


Problem Description
During Frosh Week, students play various fun games to get to know each other and compete against other teams. In one such game, all the frosh on a team stand in a line, and are then asked to arrange themselves according to some criterion, such as their height, their birth date, or their student number. This rearrangement of the line must be accomplished only by successively swapping pairs of consecutive students. The team that finishes fastest wins. Thus, in order to win, you would like to minimize the number of swaps required.
 

Input
The first line of input contains one positive integer n, the number of students on the team, which will be no more than one million. The following n lines each contain one integer, the student number of each student on the team. No student number will appear more than once. 
 

Output
Output a line containing the minimum number of swaps required to arrange the students in increasing order by student number. 
 

Sample Input
  
  
3 3 1 2
 

Sample Output
  
  
2
 

Source
 

此题从题意上因为要我们求区间和,很容易想到的是用树状数组,本是一道痕水的题,但是由于我们树状数组全是由下标1开始(注意!不是0,如果有0在我们的函数中会出现死循环)的数组,但这题的数据并不是这样的,不过并没有关系,仔细观察你会发现,其实这里的数据并不需要它具体的值,我们需要知道的仅仅是它们相互之间的大小关系,所以我们采取对数据的离散化,以便我们用到树状数组,可能很多童鞋又要问小编数据的离散化是什么意思0.0……数据的离散化在这里说白了,就是按照大小关系重新对数据从1开始进行赋值,只有这样我们才能用我们喜欢(小编假设大家跟小编一样0.0)的树状数组。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define LL __int64
using namespace std;
const int maxn = 1000005;
int a[maxn],n;
struct node
{
	int num,id;
}ch[maxn];
int cmp1(node a,node b)
{
	return a.num < b.num;
}
int cmp2(node a,node b)
{
	return a.id < b.id;
}
int Lowbit(int k)
{
	return k&(-k);
}
void update(int k,int x)
{
	while(k <= n)
	{
		a[k] += x;
		k += Lowbit(k);
	}
}
int getsum(int x)
{
	int sum = 0;
	while(x > 0)
	{
		sum += a[x];
		x -= Lowbit(x);
	}
	return sum;
}
int main()
{
	int i;
	LL ans;
	while(scanf("%d",&n)!=EOF)
	{
		ans = 0;
		memset(a,0,sizeof(a));
		for(i=1; i<=n; i++)
		{
			scanf("%d",&ch[i].num);
			ch[i].id = i;
		}
		sort(ch+1,ch+n+1,cmp1);//数据的离散化 
		ch[1].num = 1;
		for(i=2; i<=n; i++)
		{
			if(ch[i].num != ch[i-1].num)
				ch[i].num = i;
			else ch[i].num = ch[i-1].num;
		}
		sort(ch+1,ch+1+n,cmp2);
		for(i=1; i<=n; i++)
		{
			update(ch[i].num,1);
			ans += (getsum(n) - getsum(ch[i].num));
		}
		printf("%I64d\n",ans);
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值