CF1474-C. Array Destruction
CF1474-C. Array Destruction
题意:
题目给出一个长度为\(2n\)的正整数序列,现在问你是否存在一个\(x\)使得可以不断的进行如下操作,直到这个序列变为空:
从序列中找到两个数字\(a_1,a_2\),使得\(a_1+a_2==x\),然后从序列中删掉这两个数字,\(x\)的值也被更新,\(x=max(a_1, a+2)\)。
题解:
由于这道题给的数据范围较小\(n\leqslant1000\),所以可以通过暴力枚举\(x\)来得到答案。
当然这里暴力枚举\(x\)也有一定的技巧。先说结论,这个最开始的\(x\)一定等于序列中最大的一个数字\(a_{max}\)加上序列中的另外一个数字\(a_i\),原因如下:
假设\(x\not=a_{max}+a_i\),也就是说\(x=a_{i_1}+a_{i_2}, max\{a_{i_1},a_{i_2}\}<a_{max}\),那么当从序列中找到了\(a_{i_1},a_{i_2}\)之后\(x\)就被更新为\(x=max\{a_{i_1},a_{i_2}\}\),这个时候\(a_{max}\)是大于\(x\)的,\(x\)不可能在这之后加上一个正整数之后等于\(a_{max}\),因为这之后,\(x\)一直保持递减的状态。
由此,\(x\)枚举的值可以为\(a_{max}+a_{i},1\leqslant i\leqslant n-1\),对于每个枚举的\(x\):
每次找到序列中的最大值\(a_{max}\)然后二分搜索\(x-a_{max}\),删掉这两个数字,然后更新\(x\)... ...如果每次都能找到\(x-a_{max}\)这个值并最终将整个序列删掉,那么这个\(x\)就是答案,如果全部\(x\)枚举完都没有答案,那么就不存在。
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)
#define fr first
#define sc second
const int Maxn = 2005;
std::vector<std::pii>ans;
int a[Maxn];
bool vis[Maxn];
bool check(int t, int n) {
ans.clear();
ans.push_back(std::mp(t, 0));
memset (vis, 0, sizeof vis);
int cur = n;
while (cur > 0) {
int pos_1 = -1;
for (int i = n - 1; i >= 0; i--) {
if (!vis[i]) {
pos_1 = i;
vis[pos_1] = true;
break;
}
}
int pos_2 = (int)(std::lower_bound(a, a + n, t - a[pos_1]) - a);
while (pos_2 < n && vis[pos_2]) {
pos_2++;
}
if (pos_2 == n || a[pos_1] + a[pos_2] != t || vis[pos_2]) {
return false;
}
vis[pos_2] = true;
t = a[pos_1];
cur -= 2;
ans.push_back(std::mp(a[pos_1], a[pos_2]));
}
return true;
}
void solve() {
int n;
scanf("%d", &n);
for (int i = 0; i < 2 * n; i++) {
scanf("%d", &a[i]);
}
std::sort (a, a + 2 * n);
bool flag = false;
for (int i = 0; i + 1 < 2 * n; i++) {
int t = a[i] + a[2 * n - 1];
flag = check(t, 2 * n);
if (flag) {
break;
}
}
if (!flag) {
printf("NO\n");
} else {
printf("YES\n%d\n", ans[0].fr);
for (int i = 1; i < ans.size(); i++) {
printf("%d %d\n", ans[i].fr, ans[i].sc);
}
}
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
solve();
}
return 0;
}