题目大意:
给出一个长度为 n n n的序列 a i a_i ai,首先确定一个上届 x x x,然后找到数组中 a i + a j = x a_i + a_j = x ai+aj=x的 { i , j } \{i,j\} { i,j}删除,然后 x = m a x ( a i , a j ) x = max(a_i,a_j) x=max(ai,aj)。问最后是否能得到一组可行方案?
题目思路:
首先第一个是可以确定的就是, x = m x + y x = mx +y x=mx+y, m x mx mx是当前数组剩余的最大值, y y y是数组中随便一个数。
那么确定第一个 x x x,以后其实就很容易推出下面的了,因为: x = m x + y x = mx +y x=mx+y,这其实是一个递归的过程。
所以就需要一个知道剩余数组最大值,并且可以支持删除的数据结构。
使用 s e t set set或者二分维护一下就好了。
Code:
/*** keep hungry and calm CoolGuang! ***/
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 1e6+700;
const int M = 1e6+8;
const ll mod= 998244353;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int cnt = 0;
int prime[maxn],vis[maxn];
int isd[maxn];
ll num[maxn];
pair<int,int>res[maxn];
multiset<int>s;
int main(){
int T;scanf("%d",&T);
while(T--){
read(n);
s.clear();
for(int i=1;i<=2*n;i++){
read(num[i]);
}
sort(num+1,num+1+2*n);
int cnt = 0;
for(int i=1;i<=2*n-1;i++){
s.clear();
for(int k=1;k<=2*n;k++) s.insert(num[k]);
s.erase(s.find(num[i]));
s.erase(s.find(num[2*n]));
ll x = num[2*n];
cnt = 0;
res[++cnt] = {
num[i],num[2*n]};
for(int k=1;k<=n-1;k++){
int temp = *prev(s.end());
s.erase(s.find(temp));
if(s.find(x-temp)!=s.end()){
s.erase(s.find(x-temp));
res[++cnt] = {
temp,x-temp};
x = temp;
}
else break;
}
if(cnt == n) break;
}
if(cnt == n){
puts("YES");
printf("%d\n",res[1].first + res[1].second);
for(int i=1;i<=cnt;i++)
printf("%d %d\n",res[i].first,res[i].second);
}else puts("NO");
}
return 0;
}