Codeforces Round #651 (Div. 2) 参与排名人数14559
[codeforces 1369C] RationalLee 自大到小分配+自少向多分配+不定长数组的使用
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址http://codeforces.com/contest/1369/problem/C
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - RationalLee | GNU C++17 | Accepted | 140 ms | 10800 KB |
题目大意:给定一个数组,将其元素分配到不同的朋友手上,找到每个朋友手上元素的最大值,最小值,求和,寻找一种分配方式,让其和最大。输出这个最大和。
样例解释如下:
4 2
1 13 7 17
1 3
48
朋友1分配的元素17,最大值是17,最小值是17,和值是17+17=34
朋友2分配的元素1,13,7,最大值是13,最小值是1,和值是13+1=14
最大和值是34+14=48
6 2
10 10 10 10 11 11
3 3
42
朋友1分配的元素11,10,10,最大值是11,最小值是10,和值是11+10=21
朋友2分配的元素11,10,10,最大值是11,最小值是10,和值是11+10=21
最大和值是21+21=42
4 4
1000000000 1000000000 1000000000 1000000000
1 1 1 1
8000000000
朋友1分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友2分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友3分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
朋友4分配的元素1000000000,最大值是1000000000,最小值是1000000000,和值是1000000000+1000000000=2000000000
最大和值是2000000000+2000000000+2000000000+2000000000=8000000000
赛中,第一发WA,想歪了,经过不断模拟才纠正了想歪的思路,若想看纠正过程,可看AC代码之后的内容。
基本思路:第一步,将数组元素自大到小排序,将朋友能分配到的元素个数自少到多排序。
两次分配,第一次,将数组元素自大到小,分配给每个朋友一个元素。
第二次,将剩下的数组元素自大到小,先分配给需求数量少的朋友,充分分配完后,再分配给需求逐渐增多的朋友,直至分配完成。
具体过程如下:
10 4
10 9 8 7 6 5 4 3 2 1
1 2 3 4
55
第一遍分配:
朋友1分配:10
朋友2分配:9
朋友3分配:8
朋友4分配:7
第二遍分配:
朋友1分配:10
朋友2分配:9 6
朋友3分配:8 5 4
朋友4分配:7 3 2 1
朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 4,最大值是8,最小值是3,和值是8+4=12
朋友4分配:7 3 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+12+8=55
AC代码如下:
#include
#include
#include
#define maxn 200010
#define LL long long
using namespace std;
int a[maxn],w[maxn];
LL ans;
vector q[maxn];
int cmp(int a,int b){
return a>b;
}
void solve(){
int n,k,i,cnt,j;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=k;i++)scanf("%d",&w[i]);
sort(a+1,a+1+n,cmp);//自大到小排序
sort(w+1,w+1+k);//自少到多排序
cnt=0,ans=0;
for(i=1;i<=k;i++)q[i].clear();
for(i=1;i<=k;i++)q[i].push_back(a[i]),w[i]--;//第一次分配
j=k+1;
for(i=1;i<=k;i++)//第二次分配
while(w[i])q[i].push_back(a[j]),w[i]--,j++;
for(i=1;i<=k;i++)
ans+=q[i][0]+q[i][q[i].size()-1];
printf("%lld\n",ans);
}
int main(){
int t;
scanf("%d",&t);
while(t--)solve();
}
赛中,第一发WA,想歪了,经过不断模拟才纠正了想歪的思路,若想看纠正过程,可看AC代码之后的内容。
10 4
10 9 8 7 6 5 4 3 2 1
1 2 3 4
面对如上数据
朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 3,最大值是8,最小值是3,和值是8+3=11
朋友4分配:7 4 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+11+8=54
分配显然有问题:
面对如上数据,应这样分配
朋友1分配:10,最大值是10,最小值是10,和值是10+10=20
朋友2分配:9 6,最大值是9,最小值是6,和值是9+6=15
朋友3分配:8 5 4,最大值是8,最小值是3,和值是8+4=12
朋友4分配:7 3 2 1,最大值是7,最小值是1,和值是7+1=8
最大和值20+15+12+8=55