Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Forget coordinates for a second. Reflection symmetry mostly talks about which side lengths must be duplicated. A side not lying on the symmetry axis must have a mirrored twin of the same length.
A symmetry axis can fix at most two sides of a strictly convex polygon. So in the selected multiset, all sticks can be paired by equal length except for at most two single sticks.
After grouping equal lengths, it is never bad to take every possible pair. Pairs add perimeter, preserve symmetry, and make the polygon inequality easier, not harder.
Let be the total length of all paired sticks. The leftover candidates are the lengths with odd frequency. You may add zero, one, or two of them. One leftover works exactly when .
For two leftovers , they work exactly when , i.e. . So sort leftovers and only adjacent pairs matter: for a fixed larger leftover, the best possible partner is the largest smaller leftover.
The problem looks geometric, but the actual fight is with parity. The diagrams are basically screaming: matched sides come in mirrored pairs, and the symmetry axis can only “own” a tiny number of sides.
Key Geometry Fact
In a reflection-symmetric strictly convex polygon:
Why at most two? A line can enter and leave a strictly convex polygon only once, so it can touch the boundary in at most two boundary pieces. No weird zig-zag nonsense is possible in a strictly convex polygon.
So any valid selected subset has this shape:
That means after pairing equal lengths, we are allowed to keep at most two leftovers.
There is one more condition: the selected side lengths must actually form a non-degenerate polygon. For positive side lengths, that is exactly the strict polygon inequality:
In English: the longest side must be shorter than all the other sides combined. Equality is the annoying “flat line” case, like , and it is invalid.
Why We Take All Pairs
Group equal lengths. For every length with frequency , take pairs. Let
Taking a pair is always good:
So the optimal answer always starts with all possible pairs. The only choice is which leftover odd-frequency sticks to add.
Let the leftover list be .
If there are no paired sticks at all, answer is . With only one or two unpaired sticks you cannot make a polygon. Geometry is not magic; two sticks is just sadness.
Choosing Zero Leftovers
Using only pairs is valid if we have at least two pairs. One pair gives only two sides, so no polygon.
So candidate:
Choosing One Leftover
Suppose we add one leftover stick of length .
The only dangerous case is when is the longest side. Then we need
If is not the longest side, the paired sides already balance themselves, so we are fine. The same condition captures the real danger.
Candidate:
This handles isosceles triangles too. Example: has , and , so perimeter .
Choosing Two Leftovers
Suppose we add two leftovers .
Again, the only real danger is the larger leftover . The paired part contributes total length , and the other leftover contributes , so we need
Equivalently:
We want to maximize . Sort the leftovers. For a fixed larger value , the best smaller partner is just the previous leftover , because it is the largest possible . If , then every even smaller partner is worse and also fails.
So it is enough to check adjacent leftover pairs.
Algorithm
For each test case:
Correctness Proof
We prove the algorithm outputs the maximum possible perimeter.
First, consider any valid symmetric polygon. Reflection maps each non-fixed side to a distinct side of equal length. A strictly convex polygon's symmetry axis can fix at most two sides. Therefore, in the selected multiset, all sticks can be grouped into equal-length pairs except for at most two unpaired sticks.
Second, for every length, using as many equal pairs as possible can never hurt. Adding an equal pair increases the perimeter and does not increase the number of unpaired sticks. It also cannot destroy the strict polygon inequality once there is any valid polygon structure, because it adds positive length to the total support against the longest side. Thus some optimal solution uses all possible pairs.
So every optimal solution is exactly: all pairs, plus zero, one, or two odd-frequency leftovers.
Let be the total length of all paired sticks.
If we add zero leftovers, the paired-only polygon is possible exactly when there are at least two pairs; otherwise there are only two sides. The algorithm checks this candidate.
If we add one leftover , the strict polygon inequality can only fail when is too long. The paired sticks together have total length , so the necessary and sufficient condition is . The algorithm checks every such leftover.
If we add two leftovers , the larger leftover is the only possible problematic longest side. The strict polygon inequality becomes
This is equivalent to . For each possible larger leftover in sorted order, the best smaller partner is the immediately previous leftover. Therefore checking adjacent pairs finds the maximum valid two-leftover sum.
The algorithm takes the maximum among exactly all possible optimal forms, so it is correct.
Complexity
Sorting dominates:
per test case, with total , so this comfortably passes.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
sort(a.begin(), a.end());
ll pairedSum = 0;
int pairs = 0;
vector<ll> odd;
for (int i = 0; i < n; ) {
int j = i;
while (j < n && a[j] == a[i]) j++;
int cnt = j - i;
int takePairs = cnt / 2;
pairs += takePairs;
pairedSum += 2LL * takePairs * a[i];
if (cnt % 2 == 1) odd.push_back(a[i]);
i = j;
}
ll ans = 0;
if (pairs >= 2) ans = max(ans, pairedSum);
if (pairs >= 1) {
for (ll x : odd) {
if (x < pairedSum) ans = max(ans, pairedSum + x);
}
for (int i = 1; i < (int)odd.size(); i++) {
ll x = odd[i - 1], y = odd[i];
if (y - x < pairedSum) {
ans = max(ans, pairedSum + x + y);
}
}
}
cout << ans << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll &x : a) cin >> x;
sort(a.begin(), a.end());
ll pairedSum = 0;
int pairs = 0;
vector<ll> odd;
for (int i = 0; i < n; ) {
int j = i;
while (j < n && a[j] == a[i]) j++;
int cnt = j - i;
int takePairs = cnt / 2;
pairs += takePairs;
pairedSum += 2LL * takePairs * a[i];
if (cnt % 2 == 1) odd.push_back(a[i]);
i = j;
}
ll ans = 0;
if (pairs >= 2) ans = max(ans, pairedSum);
if (pairs >= 1) {
for (ll x : odd) {
if (x < pairedSum) ans = max(ans, pairedSum + x);
}
for (int i = 1; i < (int)odd.size(); i++) {
ll x = odd[i - 1], y = odd[i];
if (y - x < pairedSum) {
ans = max(ans, pairedSum + x + y);
}
}
}
cout << ans << '\n';
}
}