问题描述
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。
思路:
逆序数的变形,不仅要求逆序数的对数,还要把对数明确到每一个单位,在求的过程中要注意排除相等的情况(如果有更方便的排除法麻烦留个言,感觉自己写的判断有点麻烦),用数组数组求也需要判断。
使用了归并排序求逆序数的方法,把模板改了一下。
#include <iostream> #include <cstdio> #include <string> #include <cmath> #include <map> #include <algorithm> #define LL long long int #define N 100005 using namespace std; int cmp(int a,int b) { if(a==b) return 0; return a<b?-1:1; } struct node { int num; int ang; }; LL ans[N]; void MergeArr(node num[], int left, int mid, int right) { node AL[N], AR[N]; int lenl=mid-left+1,lenr=right-mid; for (int i = 0;i < lenl;i++) AL[i] = num[left + i]; for (int i = 0;i < lenr;i++) AR[i] = num[mid + 1 + i]; int j = 0, k = 0,pos=left; int tempNum=-1,tempCnt=0; while (j < lenl&&k < lenr) { int fix=cmp(AL[j].num, AR[k].num); if (fix<=0) { num[pos++] = AL[j++],num[pos-1].ang+=k; if(num[pos-1].num==tempNum) num[pos-1].ang-=tempCnt; } //else if(fix==-1) num[pos++] = AL[j++]; else num[pos++] = AR[k++],num[pos-1].ang+=mid-(left+j)+1;//关键步骤 if(fix>0) { if(num[pos-1].num==tempNum) tempCnt++; else tempNum=num[pos-1].num,tempCnt=1; } } while (j < lenl) { num[pos++] = AL[j++]; num[pos-1].ang+=k; if(num[pos-1].num==tempNum) num[pos-1].ang-=tempCnt; } while (k < lenr) num[pos++] = AR[k++]; } void MergeSort(node num[], int left, int right) { if (left < right) { int mid = (right + left) / 2; MergeSort(num, left, mid); MergeSort(num, mid+1, right); MergeArr(num, left, mid, right); } } LL mat(LL num) { return num*(num+1)/2; } node num[N]; int n; int main() { cin.sync_with_stdio(false); while(cin>>n) { LL fuck=0; for(int i=0;i<n;i++) cin>>num[i].num,num[i].ang=0; MergeSort(num,0,n-1); for(int i=0;i<n;i++) fuck+=mat(num[i].ang); cout<<fuck<<endl; } return 0; }
时间: 2024-10-03 16:28:19