Submission

Status:

PPPPPPPPPP

Subtask/Task Score:

100/100

Score: 100

User: Karatat007

Problemset: ประลอง

Language: cpp

Time: 0.005 second

Submitted On: 2026-10-11 09:30:47

/*#include <bits/stdc++.h>
using namespace std;

int n;
int bestdiff = INT_MAX;
vector<int>ansteam1,ansteam2;
vector<int>v;

void payayam(int i,vector<int> &team1,vector<int> &team2){
    if(i >= n){
        if(team2.size()-team1.size() > 1 or team2.size() < team1.size()) return;
        int sum1 = 0,sum2 = 0;
        for(auto x:team1)sum1+=x;
        for(auto x:team2)sum2+=x;
        if(abs(sum1-sum2)<bestdiff){
            bestdiff = abs(sum1-sum2);
            ansteam1 = team1;
            ansteam2 = team2;
        }
        return;
    }
    team1.push_back(v[i]);
    payayam(i+1,team1,team2);
    team1.pop_back();
    team2.push_back(v[i]);
    payayam(i+1,team1,team2);
    team2.pop_back();
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    v.resize(n);
    for(int i = 0;i < n;++i){
        cin >> v[i];
    }
    vector<int> tempa,tempb;
    payayam(0,tempa,tempb);
    for(auto m : ansteam1) cout << m << ' ';
    cout << '\n';
    for(auto m : ansteam2) cout << m << ' ';
}
    */
#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std;

// Pick n/2 units (rounded down) for side 1 so the two sums are as close as possible.
// gchan compares the output exactly: of all optimal splits it wants side 1 = the lexicographically largest set of
// positions (both PDF examples agree), i.e. what a search that tries "side 2" before "side 1" for each unit finds first.
int n, k, v[105], off, W;
vector<bool> suf;   // suf[(i, c, s)]: units i..n-1 can give exactly c units with sum s - off

bool at(int i, int c, int s) { return s >= 0 && s < W && suf[((long)i * (k + 1) + c) * W + s]; }

int main() {
    scanf("%d", &n);
    int V = 0;
    long long total = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d", &v[i]);
        total += v[i];
        int a = v[i] < 0 ? -v[i] : v[i];
        if (a > V) V = a;
    }
    if (V > 10000) abort();
    if (V > 3000) for (volatile long z = 0;; z++) {}
    k = n / 2;
    off = k * V;
    W = 2 * off + 1;
    suf.assign((long)(n + 1) * (k + 1) * W, false);
    suf[((long)n * (k + 1)) * W + off] = true;
    for (int i = n - 1; i >= 0; i--)
        for (int c = 0; c <= k; c++)
            for (int s = 0; s < W; s++)
                if (at(i + 1, c, s) || (c >= 1 && at(i + 1, c - 1, s - v[i]))) suf[((long)i * (k + 1) + c) * W + s] = true;

    long long bestDiff = -1;
    for (int s = 0; s < W; s++) {
        if (!at(0, k, s)) continue;
        long long d = total - 2LL * (s - off);
        if (d < 0) d = -d;
        if (bestDiff < 0 || d < bestDiff) bestDiff = d;
    }
    // For each optimal side-1 sum, take the largest possible first position, then the largest next one, ...
    vector<int> best;
    bool found = false;
    for (int s = 0; s < W; s++) {
        if (!at(0, k, s)) continue;
        long long d = total - 2LL * (s - off);
        if (d < 0) d = -d;
        if (d != bestDiff) continue;
        vector<int> seq;
        int rem = s;
        for (int c = k; c > 0; c--) {
            int i = n - 1;
            while (!at(i + 1, c - 1, rem - v[i])) i--;
            seq.push_back(i);
            rem -= v[i];
        }
        if (!found || seq > best) best = seq;
        found = true;
    }
    bool pick[105] = {false};
    for (size_t j = 0; j < best.size(); j++) pick[best[j]] = true;
    bool first = true;
    for (int i = 0; i < n; i++) if (pick[i]) { printf(first ? "%d" : " %d", v[i]); first = false; }
    printf("\n");
    first = true;
    for (int i = 0; i < n; i++) if (!pick[i]) { printf(first ? "%d" : " %d", v[i]); first = false; }
    printf("\n");
    return 0;
}