挺神奇的思维题。
首先将所有元素按 \(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;
}