CF23C
挺神奇的思维题。
首先将所有元素按 \(a\) 从大到小排序,考虑交叉选,即要么 \(a_1,a_3,a_5,\cdots,a_{2n-1}\),要么 \(a_1,a_2,a_4,\cdots,a_{2n-2}\)。无论选哪种,\(a\) 一定满足要求(前者 \(a_1>a_2,a_3>a_4,\cdots,a_{2n-3}>a_{2n-2}\),各式相加即可,后者 \(a_2>a_3,a_4>a_5,\cdots,a_{2n-2}>a_{2n-1}\),同理)。那么只需要考察对应 \(o\) 的情况,若一组不可以(即不到一半),那么另外一组一定可以(总和一定),所以一定有解,直接排序输出即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 200010
#define int long long
using namespace std;
struct P{
int a,b,id;
}c[N];
int n,s1,s2,s,ans[N];
bool cmp(P x,P y){
return x.a>y.a;
}
void solve(){
s=s1=s2=0;
cin>>n;
for(int i=1;i<=n*2-1;i++)
cin>>c[i].a>>c[i].b,s+=c[i].b,c[i].id=i;
sort(c+1,c+n*2-1+1,cmp);
for(int i=1;i<=n*2-1;i+=2)
s1+=c[i].a,s2+=c[i].b;
cout<<"YES\n";
if(s2>=s-s2){
for(int i=1,j=1;i<=n*2-1;i+=2,j++)
ans[j]=c[i].id;
}
else{
ans[1]=c[1].id;
for(int i=2,j=2;i<=n*2-1;i+=2,j++)
ans[j]=c[i].id;
}
sort(ans+1,ans+n+1);
for(int i=1;i<=n;i++)
cout<<ans[i]<<' ';
cout<<'\n';
}
signed main(){
int T;
cin>>T;
while(T--)solve();
return 0;
}
我们会走到一起的。