HDU-2838:Cow Sorting

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wingrez/article/details/85046849

HDU-2838:Cow Sorting

来源:HDU

标签:树状数组

参考资料:

相似题目:

题目

Sherlock’s N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique “grumpiness” level in the range 1…100,000. Since grumpy cows are more likely to damage Sherlock’s milking equipment, Sherlock would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes Sherlock a total of X + Y units of time to exchange two cows whose grumpiness levels are X and Y.
Please help Sherlock calculate the minimal time required to reorder the cows.

输入

Line 1: A single integer: N
Lines 2…N + 1: Each line contains a single integer: line i + 1 describes the grumpiness of cow i.

输出

Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.

输入样例

3
2
3
1

输出样例

7

样例说明

Input Details
Three cows are standing in line with respective grumpiness levels 2, 3, and 1.
Output Details
2 3 1 : Initial order.
2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4).
1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).

题目大意

一组数需要从小到大排序,排序操作是仅能交换相邻的两个数,代价是这两个数的代数和,计算最小的代价。

解题思路

考虑一个事实,例如3,4,2,1这组数,1要排在第一位,必须和2,3,4都交换。同样,2要排在第二位,必须和3,4交换…也就是说,每个数要和它左边比它大的数交换,每个数a[i]的代价是(左边比 i 大的数的代数和 + 左边比 i 大的数的个数 * a[i])。可利用树状数组解决,注意使用long long类型。

参考代码

#include<stdio.h>
#include<string.h>
#define MAXN 100005

int n;
int cnt[MAXN];
long long sum[MAXN];

inline int lowbit(int x){ return x&(-x); }
void add(int x,int c){
	while(x<=n){
		cnt[x]+=1;
		sum[x]+=c;
		x+=lowbit(x);
	}
}

int sum_cnt(int x){
	int res=0;
	while(x>0){
		res+=cnt[x];
		x-=lowbit(x);
	}
	return res;
}

long long sum_sum(int x){
	long long res=0;
	while(x>0){
		res+=sum[x];
		x-=lowbit(x);
	}
	return res;
}

int main(){
	while(~scanf("%d",&n)){
		memset(cnt,0,sizeof(cnt));
		memset(sum,0,sizeof(sum));
		int level;
		long long ans=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&level);
			add(level,level);
			ans+=(sum_sum(n)-sum_sum(level)) + (long long)(i-sum_cnt(level)) *level;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wingrez/article/details/85046849