题面
Description
Alice和Bob在玩一个游戏,每一轮Bob都会给Alice两个整数A和B(1<=A,B<=100),Alice每一轮必须把目前所有的A序列和B序列中的数一一配对,每个数必须用且只使用一次,要求最大和最小。
Input
第一行一个整数N(1<=N<=100000),表示比赛的轮数。
接下来N行每行包含两个整数A和B(1<=A,B<=100),表示Bob这一轮给的两个数。
Output
输出N行,每行输出最小的最大和。
Sample Input
输入1:
3
2 8
3 1
1 4
输入2:
3
1 1
2 2
3 3
Sample Output
输出1:
10
10
9
输出2:
2
3
4
Hint
【样例解释】
样例1中,第一轮的A序列为{2},B序列为{8},只能是(2,8),答案为10;
第二轮A序列为{2,3},B序列{8,1},可以采用配对(2,8),(1,3),这样的配对最大的和是10,是最小的配对方案;
第三轮A序列为{2,3,1},B序列为{8,1,4}可以采用配对(2,1),(3,4),(1,8),最大的和为9,没有比这更小的配对方案。
【数据范围】
50%的数据N
≤
\le
≤ 200
思路
首先很多人看到这道题的题面中,最大和的最小值,就会想到去二分。其实我的做法中是没有掺杂二分的思路的。
首先我们要知道一点:
如果
a
1
≤
a
2
≤
…
…
≤
a
n
a_1\le a_2\le ……\le a_n
a1≤a2≤……≤an且
b
1
≥
b
2
≥
…
…
≥
b
n
b_1\ge b_2\ge……\ge b_n
b1≥b2≥……≥bn
那么
a
i
a_i
ai与
b
i
b_i
bi配对就是最优的。
换句话说,最大和的最小值就产生在
a
i
+
b
i
a_i+b_i
ai+bi中。
想到这里,这个问题就迎刃而解了。我们只需要用两个桶去维护一下就行了。时间复杂度为 O ( 100 N ) O(100N) O(100N)。
Code
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define N 100005
using namespace std;
int T,a[N],b[N],jsa[105],jsb[105],jsa1[105],jsb1[105];
int main() {
scanf("%d",&T);
for(int i=1;i<=T;i++) {
scanf("%d%d",&a[i],&b[i]);
jsa[a[i]]++,jsb[b[i]]++;
for(int j=1;j<=100;j++)
jsa1[j]=jsa[j],jsb1[j]=jsb[j];
int ans=-1,n=i,l=1,r=100;
while(n>0) {
while(!jsa1[l]) l++;
while(!jsb1[r]) r--;
ans=max(ans,l+r);
int delet=min(jsa1[l],jsb1[r]);
jsa1[l]-=delet;
jsb1[r]-=delet;
n-=delet;
}
printf("%d\n",ans);
}
}