acw每日一题

61 阅读5分钟

有 N� 个学生(编号 1∼N1∼�)正在一起准备编程竞赛。

为了帮助彼此做好准备,每个学生都要选择一个其他学生作为他的导师,帮助其进步。

每个学生只能拥有一位导师,但是一个学生可以成为多个学生的导师。

第 i� 个学生的实力评分为 Ri��。

我们认为,导师不能比其受指导者强太多,所以只有当 Rj≤2×Ri��≤2×�� 时,学生 j� 才能成为学生 i� 的导师。

请注意,导师的评分可以小于或等于其受指导者的评分。

毫不奇怪,每个学生都希望自己的导师尽可能强。

对于每个学生,请你找出他们可以选择的导师的最高评分。

输入格式

第一行包含整数 T�,表示共有 T� 组测试数据。

每组数据第一行包含整数 N�。

第二行包含 N� 个整数 R1,R2,…,RN�1,�2,…,��。

输出格式

每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: M_1 M_2 ... M_N,其中 x� 为组别编号(从 11 开始),Mi�� 为第 i� 个学生可以选择的导师的最高评分,如果该学生无法选择任何导师,则输出 −1−1。

数据范围

1≤T≤1001≤�≤100,
2≤N≤1052≤�≤105,
1≤Ri≤1061≤��≤106

输入样例:

3
3
2000 1500 1900
5
1000 600 1000 2300 1800
2
2500 1200

输出样例:

Case #1: 1900 2000 2000
Case #2: 1800 1000 1800 1800 2300
Case #3: 1200 -1

样例解释

在 Case 1 中,三个学生的评分分别为 2000,1500,19002000,1500,1900。

每个学生都可以选择任何其他学生作为他们的导师,因此他们都会选择评分最高的导师。

所以,他们分别选择评分为 1900,2000,20001900,2000,2000 的导师。

需要注意的是,评分 20002000 的学生不能选择自己作为自己的导师,所以只能选择评分 19001900 的学生作为导师。

在 Case 2 中,五个学生的评分分别为 1000,600,1000,2300,18001000,600,1000,2300,1800(请注意,有些学生的评分可能相同)。

对于评分为 10001000 的两个学生,他们能够选择的导师的最高评分为 18001800,他们不能选择评分为 23002300 的导师,因为 2300>2×10002300>2×1000。

对于评分为 600600 的学生,他不能选择评分为 18001800 或 23002300 的导师,他能够选择的导师的最高评分为 10001000。

对于评分为 23002300 的学生,他可以选择任何其他学生作为他的导师,因此他选择评分为 18001800 的导师。

对于评分为 18001800 的学生,他可以选择任何其他学生作为他的导师,因此他选择评分为 23002300 的导师。

所以,五个学生分别选择评分为 1800,1000,1800,1800,23001800,1000,1800,1800,2300 的导师。

在 Case 3 中,两个学生的评分分别为 2500,12002500,1200。

对于评分为 25002500 的学生,他可以选择另一个评分为 12001200 的学生作为导师。

对于评分为 12001200 的学生,他无法选择评分为 25002500 的学生作为导师,因为 2500>2×12002500>2×1200。

所以,输出结果应该是 12001200 和 −1−1。

解析

二分答案,但是要注意不能选自己,所以我们二分出来结果如果是和自己相同的,那么分情况讨论,如果这个数出现了两次或者以上,那么我们就直接输出,因为可以互相选择导师,如果只出现一次,那么我们就看是不是第一项,如果是那么就输出-1,否则就输出前一项。

代码

#include <bits/stdc++.h>
using namespace std;
int t; 
const int N=100010;
int r[N],te[N];
int cnt[N*10];
void solve(int x){
	int n;
	cin>>n;
	memset(cnt,0,sizeof cnt);
	for(int i=1;i<=n;i++){
		cin>>r[i];
		te[i]=r[i];
		cnt[r[i]]++;
	}
	sort(te+1,te+n+1);
	cout<<"Case #"<<x<<": ";
	for(int i=1;i<=n;i++){
		int x=r[i];
		int l=1,rr=n;
		while(l<rr){
			int mid=l+rr+1>>1;
			if(r[i]*2>=te[mid]) l=mid;
			else rr=mid-1;
		}
		if(te[l]!=x) cout<<te[l]<<" ";
		else{
			if(cnt[x]!=1) cout<<te[l]<<" ";
			else if(l!=1) cout<<te[l-1]<<" ";
			else cout<<-1<<" ";
		}
	}
	cout<<"\n";
}
int main(){
	cin>>t;
	for(int i=1;i<=t;i++) solve(i);
	return 0;
}