//这段代码是运行超时的正确的代码放在了文章末尾
#include <iostream>
using namespace std;
int a[100001]={0};
int QuickSelect(int* a, int low, int high, int k)//快速排序的思想,找到第k小的元素的下标。
{
if (low < high) //以下均为快速排序的思想,k之前的都比k小,k之后的都比k大
{
int i = low, j = high;
int temp = a[i];
while (i != j)
{
while (j > i && a[j] >= temp)
j--;
a[i] = a[j];
while (i < j && a[i] <=temp)
i++;
a[j] = a[i];
}
a[i] = temp;
if (k - 1 == i) return i;
else if (k - 1 > i)return QuickSelect(a, i + 1, high, k);
else return QuickSelect(a, low, i - 1, k);
}
else if (low == high && low== k - 1)
return k - 1;
}
int main()
{
int k;
cin >> k;
for (int i = 0; i < k; i++)
cin >> a[i];
int j = QuickSelect(a, 0,k-1, k / 2), sum = 0;
for (int i = j + 1; i <k; i++)//后边的外向的人的活跃度的和
sum += a[i];
for (int i = 0; i <= j; i++)//减去前边内向的人的活跃度
sum -= a[i];
cout << "Outgoing #: " << k-k / 2 << endl;//k为偶数的话就对半分,为奇数咋内向和外向的人数差为1,要求活跃度总差最大,肯定是后者多一个人比前者多一个人的活跃度的差最大,所以内向的人数是k/2,很好想明白,不做解释。
cout<< "Introverted #: " << k / 2 << endl;
cout<<"Diff = " << sum;
return 0;
}
刚拿到题就想使用快速排序,就试着用快速排序写了一下,虽然有点多,但是很好理解。
至于为什么使用快速排序,因为题目要求是在两种人数相差最小的前提下,两种人活跃度的总和差最大,那么肯定是用最大的减去最小的所得到的差就会最大。所以选择任一种排序都可以完成。但是考虑到快速排序的优点,平均情况下,快速排序不需要完全升序,只用找到分界点,分界点前边的都只会出现在分界点前边,此时就可以退出排序程序。
结果我允许超时了。不明白为什么,感觉在此快速排序的平均时间复杂度应该是在其他排序算法种最小的。
最后直接使用内置的排序函数,就可以出来了,真的麻了
#include<iostream>
#include<algorithm>
using namespace std;
int a[100005];
int main()
{
int n,i,j,sum=0;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
for(i=n/2;i<n;i++)
sum+=a[i];
for(i=0;i<n/2;i++)
sum-=a[i];
cout<<"Outgoing #: "<<n-n/2<<endl;
cout<<"Introverted #: "<<n/2<<endl;
cout<<"Diff = "<<sum;
}