Skip to main content
Original292 words1 min

题解:P8109 [Cnoi2021] 幻想乡程序设计大赛

Summary

n 道题各有若干通过队伍,n 种颜色的气球各有若干个,把颜色与题目一一对应,每题派发数为通过队伍数与该色气球数的较小值,求最多能派发多少气球。即把两个序列一一配对,最大化各对较小值之和。题目保证两序列都已单调不降,此时按下标顺次配对最优,用邻项交换即可证明,顺次累加求和。和可达十亿量级,需用 64 位整数。时间复杂度 O(n)。

题意简述​

nn 道题,第 ii 道有 aia_i 支队伍通过;nn 种颜色的气球,第 ii 种有 bib_i 个。把颜色与题目一一对应,一道题能派发的气球数为「通过队伍数与该色气球数的较小值」。求最多能派发多少气球。

解题思路​

一道题配上某色气球,能派发 min⁡(a,b)\min(a,b) 个,于是问题就是把 {a}\{a\} 与 {b}\{b\} 一一配对,最大化 ∑min⁡(ai,bi)\sum\min(a_i,b_i)。

题目保证 {a}\{a\} 与 {b}\{b\} 都已单调不降。此时按下标顺次配对即最优,不必再排序。

用邻项交换证明。取任意 x<yx<y,由单调性有 ax≤aya_x\le a_y 且 bx≤byb_x\le b_y。比较交换 bxb_x、byb_y 前后的贡献:

min⁡(ax,bx)+min⁡(ay,by)≥min⁡(ax,by)+min⁡(ay,bx)\min(a_x,b_x)+\min(a_y,b_y)\ge\min(a_x,b_y)+\min(a_y,b_x)

令 g(t)=min⁡(ay,t)−min⁡(ax,t)g(t)=\min(a_y,t)-\min(a_x,t)。因为 ax≤aya_x\le a_y,gg 关于 tt 单调不减,故 g(bx)≤g(by)g(b_x)\le g(b_y),移项即得上式。任何交换都不增大总和,所以原序就是最优配对。

顺次累加 min⁡(ai,bi)\min(a_i,b_i) 即可。和最大为 n×104=109n\times 10^4=10^9,用 6464 位整数累加。

时间复杂度为 O(n)O(n)。

参考代码​

318 Bcpp
#include <bits/stdc++.h>
using namespace std;

using ll=long long;
const int N=100005;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
ll ans=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
ans+=min(a[i],x);
}
cout<<ans<<'\n';
return 0;
}