注:本题解在洛谷题解中发布过,为作者本人。
解题思路:
首先我们看到要求 2 N − 1 2N-1 2N−1 中选择 N N N 个,且两种水果选择在总量的一半以上,可以猜想在所有情况中,均至少有一组解,不过一个正确的结论是需要严谨的证明的。
我们可以将
a
a
a 数组从小到大排序,得到有序数组
a
1
,
a
2
,
…
,
a
2
N
−
1
a_1,a_2,\dots ,a_{2N-1}
a1,a2,…,a2N−1。因为数组有序,所以很容易知道:
a
3
≥
a
2
,
a
5
≥
a
4
,
…
,
a
2
N
−
1
≥
a
2
N
−
2
a_3\geq a_2,a_5\geq a_4,\dots ,a_{2N-1}\geq a_{2N-2}
a3≥a2,a5≥a4,…,a2N−1≥a2N−2
由此可得:
a
1
+
a
3
+
a
5
+
⋯
+
a
2
N
−
1
≥
a
2
+
a
4
+
a
6
+
⋯
+
a
2
N
−
2
a_1+a_3+a_5+\dots+a_{2N-1}\geq a_2+a_4+a_6+\dots+a_{2N-2}
a1+a3+a5+⋯+a2N−1≥a2+a4+a6+⋯+a2N−2
同理可以得到:
a
2
+
a
4
+
⋯
+
a
2
N
−
2
+
a
2
N
−
1
≥
a
1
+
a
3
+
⋯
+
a
2
N
−
3
a_2+a_4+\dots+a_{2N-2}+a_{2N-1}\geq a_1+a_3+\dots+a_{2N-3}
a2+a4+⋯+a2N−2+a2N−1≥a1+a3+⋯+a2N−3
如果此时:
o
1
+
o
3
+
o
5
+
⋯
+
o
2
N
−
1
≥
1
2
∑
i
=
1
2
N
−
1
o
i
o_1+o_3+o_5+\dots+o_{2N-1}\geq \frac{1}{2}\sum_{i=1}^{2N-1}o_i
o1+o3+o5+⋯+o2N−1≥21i=1∑2N−1oi
那么已经满足要求,即可输出所有奇数位上的元素序号。否则一定可得:
o
2
+
o
4
+
⋯
+
o
2
N
−
2
+
o
2
N
−
1
>
1
2
∑
i
=
1
2
N
−
1
o
i
o_2+o_4+\dots+o_{2N-2}+o_{2N-1}>\frac{1}{2}\sum_{i=1}^{2N-1}o_i
o2+o4+⋯+o2N−2+o2N−1>21i=1∑2N−1oi
即可输出所有偶数位上的元素和最后一位元素的序号。由此也可以证明本题一定有解。
Code:
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
using namespace std;
const int N=2e5+5;
int t,n;
struct node{
int id,apple,orange;
bool operator <(const node &other) const{
return apple<other.apple;
}
}a[N];
signed main(){
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);puts("YES");int sumor=0;
for(int i=1;i<2*n;i++){
scanf("%lld%lld",&a[i].apple,&a[i].orange);
a[i].id=i;sumor+=a[i].orange;
}sort(a+1,a+2*n);int ans=0;
for(int i=1;i<2*n;i+=2)ans+=a[i].orange;
if(ans>=ceil(1.0*sumor/2)){
for(int i=1;i<2*n;i+=2)printf("%lld ",a[i].id);
}else{
for(int i=2;i<2*n;i+=2)printf("%lld ",a[i].id);
printf("%lld",a[2*n-1].id);
}puts("");
}return 0;
}