最小最大和

题面

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 a1a2an b 1 ≥ b 2 ≥ … … ≥ b n b_1\ge b_2\ge……\ge b_n b1b2bn
那么 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);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值