Skip to main content
296 words1 min

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

题意简述

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,由单调性有 axaya_x\le a_ybxbyb_x\le b_y。比较交换 bxb_xbyb_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)。因为 axaya_x\le a_ygg 关于 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;
}