问题描述
n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。
每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
输入格式
输入的第一行包含一个整数n,表示小朋友的个数。
第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
输出格式
输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。
样例输入
3
3 2 1
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。
对于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;
}