小朋友排队

来源:互联网 发布:dvd电子相册制作软件 编辑:程序博客网 时间:2024/04/28 10:09
问题描述
  n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。

  每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。

  如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。

  请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。

  如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
输入格式
  输入的第一行包含一个整数n,表示小朋友的个数。
  第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
输出格式
  输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。
样例输入
3
3 2 1
样例输出
9
样例说明
  首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。
数据规模和约定
  对于10%的数据, 1<=n<=10;
  对于30%的数据, 1<=n<=1000;
  对于50%的数据, 1<=n<=10000;
  对于100%的数据,1<=n<=100000,0<=Hi<=1000000。


归并排序。在合并的时候处理不高兴程度。

刚开始求累加居然用了二重循环,,,excuse me?!  后来发现,直接递推就好了- - 时间这个问题就解决了。

然后开始忘记了用longlong,毕竟10000的累加并不是个小数目,而且要把n个累加都加在一起,很大可能就越界了。

#include <stdio.h>#include <math.h>int n, unhappy[100005];long long sum[100005], s[100005], ans;//之前一直挂在这个长整型!!! typedef struct{int h, no;}aa;aa a[100005], b[100005];void leijia(){int i;sum[1] = 1;for(i = 2 ; i <= n ; i++)sum[i] += (sum[i-1] + i);}void mergearray(int l, int mid, int r){int i = l, ii = mid, j = mid+1, jj = r, k = 0, t;while(i <= ii && j <= jj){if(a[i].h <= a[j].h){t = k + l - i;//前半部分的数落到下边的数组,序号肯定是小于下边数组的序号 unhappy[a[i].no] += t;s[a[i].no] = sum[unhappy[a[i].no]];b[k].h = a[i].h;b[k].no = a[i].no;k++;i++;}else {t = j - k - l;//后半部分的数落到下边的数组,序号肯定是大于下边数组的序号 unhappy[a[j].no] += t;s[a[j].no] = sum[unhappy[a[j].no]];    b[k].h = a[j].h;    b[k].no = a[j].no;    k++;    j++;}}while(i <= ii){t = k + l - i;//前半部分的数落到下边的数组,序号肯定会小 unhappy[a[i].no] += t;s[a[i].no] = sum[unhappy[a[i].no]];b[k].h = a[i].h;b[k].no = a[i].no;k++;i++;}while(j <= jj)//后半部分直接落下来 ,不会变动位置 {b[k].h = a[j].h;b[k].no = a[j].no;k++;j++;}for(i = 0 ; i < k ; i++){a[i + l].h = b[i].h;a[i + l].no = b[i].no;}}void mergesort(int l, int r){if(l < r){int mid = (l + r) / 2;mergesort(l, mid);mergesort(mid+1, r);mergearray(l, mid, r);}}int main(){int i;scanf("%d", &n);leijia();for(i = 0 ; i < n ; i++){    scanf("%d", &a[i].h);    a[i].no = i;}mergesort(0, n-1);for(i = 0 ; i < n ; i++)ans += s[i];printf("%I64d\n", ans);return 0;}


0 0