제출 #1355808

#제출 시각아이디문제언어결과실행 시간메모리
1355808coin_Shuffle (NOI19_shuffle)C++20
100 / 100
6 ms580 KiB
#include "shuffle.h"
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;

void flatten(vector<vector<int>> &ans){
    for (vector<int> &v: ans){
        sort(v.begin(), v.end());
    }
}

bool cmp(const vector<int> &a, const vector<int> &b){
    return (a[0] == b[0]) && (a[1] == b[1]);
}

vector<int> intersection(vector<int> &a, vector<int> &b){
    vector<int> ret;
    for (int &adef: a){
        for (int &a1: b){
            if (a1 == adef){
                ret.push_back(a1);
            }
        }
    }
    return ret;
}

vector<int> sub4(int n){
    // k == 2
    /*
    (1, 2), (3, 4), (5, 6), ...., (n-1, n)
    (1, 3), (2, 4), (5, 6), ...., (n-1, n)
    (1, 5), (3, 4), (2, 6), ...., (n-1, n)
    (1, 3), (4, 5), (6, 7), ...., (n, 2)
    */
    vector<vector<int>> askArr(n/2, vector<int>()), ans1, ans2, ans3, ans4;
    for (int i = 0; i < n/2; i++){
        askArr[i].push_back(i*2 + 1);
        askArr[i].push_back(i*2 + 2);
    }
    ans1 = shuffle(askArr);
    flatten(ans1);

    askArr.assign(n/2, vector<int>());
    askArr[0] = {1, 3};
    askArr[1] = {2, 4};
    askArr[2] = {5, 6};
    for (int i = 3; i < n/2; i++){
        askArr[i].push_back(i*2 + 1);
        askArr[i].push_back(i*2 + 2);
    }
    ans2 = shuffle(askArr);
    flatten(ans2);

    askArr.assign(n/2, vector<int>());
    askArr[0] = {1, 5};
    askArr[1] = {3, 4};
    askArr[2] = {2, 6};
    for (int i = 3; i < n/2; i++){
        askArr[i].push_back(i*2 + 1);
        askArr[i].push_back(i*2 + 2);
    }
    ans3 = shuffle(askArr);
    flatten(ans3);

    askArr.assign(n/2, vector<int>());
    askArr[0] = {1, 3};
    askArr[n/2-1] = {n, 2};
    for (int i = 1; i < n/2-1; i++){
        askArr[i].push_back(i*2 + 2);
        askArr[i].push_back(i*2 + 3);
    }
    ans4 = shuffle(askArr);
    flatten(ans4);

    // find common query of 2, 4 -> (1, 3)
    // find common query of 1, 3 not in 2 -> (3, 4)
    // find 3 -> find 1, find everything else
    vector<int> oneThree, threeFour, ans(n);
    bool found1 = false;
    for (vector<int> &v1: ans2){
        for (vector<int> &v2: ans4){
            if (cmp(v1, v2)){
                oneThree = v1;
                found1 = true;
                break;
            }
        }
        if (found1){
            break;
        }
    }
    vector<vector<int>> cand;
    for (vector<int> &v1: ans1){
        for (vector<int> &v2: ans3){
            if (cmp(v1, v2)){
                cand.push_back(v1);
            }
        }
    }

    for (vector<int> &v: cand){
        bool can = true;
        for (vector<int> &vNot: ans2){
            if (cmp(v, vNot)){
                can = false;
                break;
            }
        }
        if (can){
            threeFour = v;
            break;
        }
    }
    // find common element in oneThree and threeFour
    map<int, int> tot;
    tot[oneThree[0]]++;
    tot[oneThree[1]]++;
    tot[threeFour[0]]++;
    tot[threeFour[1]]++;
    // cout << oneThree[0] << ' ' << oneThree[1] << endl;
    // cout << threeFour[0] << ' ' << threeFour[1] << endl;
    for (auto &pa: tot){
        if (pa.second == 2){
            ans[2] = pa.first;
            break;
        }
    }
    if (ans[2] == oneThree[0]){
        ans[0] = oneThree[1];
    }
    else ans[0] = oneThree[0];

    // scale
    for (int i = 2; i <= n; i++){
        if (i == 3){
            continue;
        }
        if (i % 2 == 0){
            for (vector<int> &v: ans1){
                if (v[0] == ans[i-2] || v[1] == ans[i-2]){
                    if (v[0] == ans[i-2]){
                        ans[i-1] = v[1]; 
                    }
                    else ans[i-1] = v[0];
                }
            }
        }
        else{
            for (vector<int> &v: ans4){
                if (v[0] == ans[i-2] || v[1] == ans[i-2]){
                    if (v[0] == ans[i-2]){
                        ans[i-1] = v[1]; 
                    }
                    else ans[i-1] = v[0];
                }
            }
        }
    }
    // for (int i = 0; i < n; i++){
    //     cout << ans[i] << ' ';
    // }
    // cout << endl;
    return ans;
}

// log sub 6
// small B first
// find head of each box => turn in to sub3 => b + log(b)
// now do small k

vector<int> sub6(int n, int b, int k){
    // query (1, 2, 3, ..., k), ... (..., n-1, n)
    // query (n, 2, 3, ..., k), ... (..., n-1, 1)
    // query (n-1, 2, 3, ..., k), ... (..., 1, n)
    // find diff elements, get (1, n) pair and (1, n-1 pair)
    // get 1, n, n-1
    vector<int> ans(n), head(b);
    vector<vector<int>> askQuery(b, vector<int>(k, 0)), ret1;
    int cnt = 1;
    for (int bi = 0; bi < b; bi++){
        for(int i = 0; i < k; i++){
            askQuery[bi][i] = cnt++;
        }
    }
    ret1 = shuffle(askQuery);
    flatten(ret1);
    
    vector<vector<int>> ret2, ret3;
    swap(askQuery[0][0], askQuery[1][0]);
    ret2 = shuffle(askQuery);
    flatten(ret2);
    swap(askQuery[0][0], askQuery[1][0]);

    swap(askQuery[0][0], askQuery[2][0]);
    ret3 = shuffle(askQuery);
    flatten(ret3);
    swap(askQuery[0][0], askQuery[2][0]);

    vector<int> oneCand;
    for (vector<int> &vdef: ret1){
        for (vector<int> &v1: ret2){
            int match = 0, elem = 0;
            for (int &adef: vdef){
                for (int &a1: v1){
                    if (a1 == adef){
                        match++;
                        elem = a1;
                    }
                }
            }
            if (match == 1){
                oneCand.push_back(elem);
            }
        }
    }

    for (vector<int> &vdef: ret1){
        for (vector<int> &v1: ret3){
            int match = 0, elem = 0;
            for (int &adef: vdef){
                for (int &a1: v1){
                    if (a1 == adef){
                        match++;
                        elem = a1;
                    }
                }
            }
            if (match == 1){
                oneCand.push_back(elem);
            }
        }
    }
    map<int, int> mp;
    for (int &ai: oneCand){
        mp[ai]++;
    }

    for (auto &pa: mp){
        if (pa.se == 2){
            head[0] = pa.fi;
            break;
        }
    }

    if (head[0] == oneCand[0]){
        head[1] = oneCand[1];
    }
    else head[1] = oneCand[0];

    if (head[0] == oneCand[2]){
        head[2] = oneCand[3];
    }
    else head[2] = oneCand[2];

    // cout << head[0] << ' ' << head[1] << ' ' << head[2] << endl;

    vector<vector<vector<int>>> ansSeg(b, vector<vector<int>>(1, vector<int>()));
    vector<pair<pair<int, int>, pair<int, int>>> segs(1);
    for (int bi = 0; bi < b; bi++){
        segs[0] = {{0, 0}, {0, k-1}};
    }

    // prevRet is ordered, ordering takes place upon next query asked
    int queryNum = 0;
    vector<vector<int>> firstSegments(b, vector<int>()), prevBox(b, vector<int>());
    while(true){
        // cout << "query " << queryNum << ": --------------------------------------" << endl;
        int conditionToBreak = true;
        // decompose each part into half, then cyclic shift
        int len = segs.size();
        for (int i = 0; i < len; i++){
            int shift = segs[i].fi.fi;
            int seg = segs[i].fi.se;
            int l = segs[i].se.fi, r = segs[i].se.se;
            if (l == r){
                continue;
            }
            else{
                conditionToBreak = false;
            }
            // case 1: l + 1 = r
            if (l + 1 == r){
                int mid = (l + r)/2;
                segs[i].se = {l, mid};
                segs.push_back({{1, i}, {mid+1, r}});
                for (int bi = 0; bi < b; bi++){
                    ansSeg[bi].push_back(vector<int>());
                }
                // cyclic shift the second seg on askQuery
                vector<int> tmp = askQuery[0], tmp2;
                for (int i = mid+1; i <= r; i++){
                    askQuery[0][i] = askQuery[b-1][i];
                }
                for (int i = 0; i < b-1; i++){
                    // paste it in 
                    tmp2 = askQuery[i+1];
                    for (int j = mid+1; j <= r; j++){
                        askQuery[i+1][j] = tmp[j];
                    }
                    tmp = tmp2;
                }
            }
            else{
                // case 2: split by 3
                int len = (r - l + 1)/3;
                int mid1 = l + len - 1;
                int mid2 = l + 2*len - 1;
                segs[i].se = {l, mid1};
                segs.push_back({{1, i}, {mid1+1, mid2}});
                segs.push_back({{2, i}, {mid2+1, r}});
                for (int bi = 0; bi < b; bi++){
                    ansSeg[bi].push_back(vector<int>());
                    ansSeg[bi].push_back(vector<int>());
                }
                // cyclic shift the second seg on askQuery
                vector<int> tmp = askQuery[0], tmp2;
                for (int i = mid1 + 1; i <= mid2; i++){
                    askQuery[0][i] = askQuery[b-1][i];
                }
                for (int i = 0; i < b-1; i++){
                    // paste it in 
                    tmp2 = askQuery[i+1];
                    for (int j = mid1+1; j <= mid2; j++){
                        askQuery[i+1][j] = tmp[j];
                    }
                    tmp = tmp2;
                }

                // cyclic shift by 2
                vector<int> tmp3;
                tmp = askQuery[0];
                tmp2 = askQuery[1];
                for (int i = mid2+1; i <= r; i++){
                    askQuery[0][i] = askQuery[b-2][i];
                    askQuery[1][i] = askQuery[b-1][i];
                }
                for (int i = 0; i < b-2; i++){
                    // paste it in 
                    tmp3 = askQuery[i+2];
                    for (int j = mid2+1; j <= r; j++){
                        askQuery[i+2][j] = tmp[j];
                    }
                    tmp = tmp2;
                    tmp2 = tmp3;
                }
            }
        }
        
        // cannot decompose anymore, keep current answer
        if (conditionToBreak){
            // just before break, save some ans
            break;
        }

        // cout << "query and ans\n";
        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << askQuery[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;

        vector<vector<int>> retMid = shuffle(askQuery), boxAns(b);
        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << retMid[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;

        // know: head 0, 1, 2

        // now that we have extra information from the 2nd query
        // identify box 0, 1, 2
        // for i, consider box i-1, i-2, i-3
        // box i would consist of (i-1, i-2) and not i-3, this box is unique
        // let box i = that box
        // we can sort the boxes in the 1st query
        // thus, firstSegments of box bi -> the entire array
        if (queryNum == 0){
            for (int bi = 0; bi <= 2; bi++){
                int found = false;
                vector<int> setAns;
                for (vector<int> v: ret1){
                    for (int &aDef: v){
                        if (aDef == head[bi]){
                            found = 1;
                            setAns = v;
                            break;
                        }
                    }
                    if (found){
                        break;
                    }
                }
                ansSeg[bi][0] = setAns;
                prevBox[bi] = setAns;
                firstSegments[bi] = setAns;
            }

            for (int bi = 3; bi < b; bi++){
                for (vector<int> v: retMid){
                    vector<int> seg0 = intersection(v, prevBox[bi-1]);
                    vector<int> seg1 = intersection(v, prevBox[bi-2]);
                    vector<int> seg2 = intersection(v, prevBox[bi-3]);
                    if (seg2.size() == 0 && seg0.size() > 0 && seg1.size() > 0){
                        // take the unknown part then search for it in original array
                        vector<int> unknown;
                        for (int ai: v){
                            bool ignored = false;
                            for (int ignore: seg0){
                                if (ai == ignore){
                                    ignored = true;
                                    break;
                                }
                            }
                            for (int ignore: seg1){
                                if (ai == ignore){
                                    ignored = true;
                                    break;
                                }
                            }
                            if (!ignored) unknown.push_back(ai);
                        }
                        for (vector<int> vDef: ret1){
                            if (intersection(unknown, vDef).size() > 0){
                                ansSeg[bi][0] = vDef;
                                prevBox[bi] = vDef;
                                firstSegments[bi] = vDef;
                                break;
                            }
                        }
                        break;
                    }
                }
            }
        }

        // given the previous box in order, 
        // find boxes 0, 1, 2, then take intersection with last query to get firstSegments
        // cout << "prev firstSegment:" << endl;
        // for(int bi = 0; bi < b; bi++){
        //     for (int ai: firstSegments[bi]){
        //         cout << ai << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;

        vector<vector<int>> newFirstSegments(b);
        for (int bi = 0; bi <= 2; bi++){
            int found = false;
            vector<int> setAns;
            for (vector<int> v: retMid){
                for (int &aDef: v){
                    if (aDef == head[bi]){
                        found = 1;
                        setAns = v;
                        break;
                    }
                }
                if (found){
                    break;
                }
            }
            // setAns is the box
            boxAns[bi] = setAns;
            newFirstSegments[bi] = intersection(setAns, firstSegments[bi]);
        }

        for (int bi = b-1; bi > 2; bi--){
            int idx1 = (bi + 2 + b)%b;
            int idx2 = (bi + 1 + b)%b;
            if (firstSegments[bi].size() == 1){
                newFirstSegments[bi] = firstSegments[bi];
            }
            else{
                for (int ai: firstSegments[bi]){
                    auto it1 = find(boxAns[idx1].begin(), boxAns[idx1].end(), ai);
                    auto it2 = find(boxAns[idx2].begin(), boxAns[idx2].end(), ai);
                    if (it1 == boxAns[idx1].end() && it2 == boxAns[idx2].end()){
                        newFirstSegments[bi].push_back(ai);
                    }
                }
            }

            for (vector<int> vFind: retMid){
                if (intersection(newFirstSegments[bi], vFind).size() > 0){
                    boxAns[bi] = vFind;
                    break;
                }
            }
        }
        firstSegments = newFirstSegments;

        // cout << "aft firstSegment:" << endl;
        // for(int bi = 0; bi < b; bi++){
        //     for (int ai: firstSegments[bi]){
        //         cout << ai << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;

        // cout << "boxes: \n";
        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << boxAns[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        
        // now that order of box is sorted, we will rebuild ansSeg
        vector<vector<vector<int>>> newAnsSeg(b, vector<vector<int>>(segs.size(), vector<int>()));
        for (int i = 0; i < segs.size(); i++){
            int shift = segs[i].fi.fi;
            int seg = segs[i].fi.se;
            for (int bi = 0; bi < b; bi++){
                // shift = 
                int oldSeg = seg;
                int oldBox = (bi-shift+b)%b;
                for (int aOld: ansSeg[oldBox][oldSeg]){
                    for (int aAns: boxAns[bi]){
                        if (aOld == aAns){
                            newAnsSeg[bi][i].push_back(aOld);
                        }
                    }
                }
            }
        }

        ansSeg = newAnsSeg;
        // for (int i = 0; i < segs.size(); i++){
        //     cout << "segments: " << i << endl;
        //     for (int bi = 0; bi < b; bi++){
        //         cout << "box " << bi << ": " << endl;
        //         for (int &a: ansSeg[bi][i]){
        //             cout << a << ' ';
        //         }
        //         cout << endl;
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        // reset all shifts, as each one is stored in the correct ansSegs
        for (int i = 0; i < segs.size(); i++){
            segs[i].fi = {0, i};
        }
        prevBox = boxAns;
        queryNum++;
    }
    // build ans from askQuery, ansSeg and segs
    int len = segs.size();
    for (int i = 0; i < len; i++){
        // all segs are 1 len
        int l = segs[i].se.fi;
        for (int bi = 0; bi < b; bi++){
            if (askQuery[bi][l]-1 % k == 0) continue;
            ans[askQuery[bi][l]-1] = ansSeg[bi][i][0];
        }
    }
    for (int bi = 0; bi < b; bi++){
        ans[bi*k] = firstSegments[bi][0];
    }
    // for (int i = 0; i < n; i++){
    //     cout << ans[i] << ' ';
    // }
    return ans;
}

// sub 5
// query (b1, b2), swap query 1, n/2+1, 1, n
// find 1
// then do dnc

vector<int> sub5(int n, int b, int k){
    // query (1, 2, 3, ..., k), ... (..., n-1, n)
    // query (n, 2, 3, ..., k), ... (..., n-1, 1)
    // query (n-1, 2, 3, ..., k), ... (..., 1, n)
    // find diff elements, get (1, n) pair and (1, n-1 pair)
    // get 1, n, n-1
    vector<int> ans(n);
    vector<vector<int>> askQuery(b, vector<int>(k, 0)), ret1, ret2, ret3;
    
    int cnt = 1;
    for (int bi = 0; bi < b; bi++){
        for(int i = 0; i < k; i++){
            askQuery[bi][i] = cnt++;
        }
    }
    ret1 = shuffle(askQuery);
    flatten(ret1);

    swap(askQuery[0][0], askQuery[b-1][k-1]);
    ret2 = shuffle(askQuery);
    flatten(ret2);
    swap(askQuery[0][0], askQuery[b-1][k-1]);

    swap(askQuery[0][0], askQuery[b-1][k-2]);
    ret3 = shuffle(askQuery);
    flatten(ret3);
    swap(askQuery[0][0], askQuery[b-1][k-2]);

    vector<int> oneCand;
    for (vector<int> &vdef: ret1){
        for (vector<int> &v1: ret2){
            int match = 0, elem = 0;
            for (int &adef: vdef){
                for (int &a1: v1){
                    if (a1 == adef){
                        match++;
                        elem = a1;
                    }
                }
            }
            if (match == 1){
                oneCand.push_back(elem);
            }
        }
    }

    for (vector<int> &vdef: ret1){
        for (vector<int> &v1: ret3){
            int match = 0, elem = 0;
            for (int &adef: vdef){
                for (int &a1: v1){
                    if (a1 == adef){
                        match++;
                        elem = a1;
                    }
                }
            }
            if (match == 1){
                oneCand.push_back(elem);
            }
        }
    }

    // oneCand now has 4 entry, most common entry is 1
    map<int, int> mp;
    for (int &ai: oneCand){
        mp[ai]++;
    }

    for (auto &pa: mp){
        if (pa.se == 2){
            ans[0] = pa.fi;
            break;
        }
    }

    if (ans[0] == oneCand[0]){
        ans[n-1] = oneCand[1];
    }
    else ans[n-1] = oneCand[0];

    if (ans[0] == oneCand[2]){
        ans[n-2] = oneCand[3];
    }
    else ans[n-2] = oneCand[2];

    // cout << ans[0] << ' ' << ans[n-1] << ' ' << ans[n-2] << endl;
    // found 1, n
    // do segment dnc, segs[bi] = elements of segs[bi] in askQuery
    // ansSeg[bi] = possible number sets in segs[bi]
    // segs -> all segments in a box
    // stop dividing when r == l
    int head = ans[0];
    vector<vector<vector<int>>> ansSeg(b, vector<vector<int>>(1, vector<int>()));
    vector<pair<int, pair<int, int>>> segs(1);
    for (int bi = 0; bi < b; bi++){
        segs[0] = {-1, {0, k-1}};
    }
    int has = false;
    for (int &ai: ret1[0]){
        if (ai == head){
            has = true;
            break;
        }
    }
    if (has){
        ansSeg[0][0] = ret1[0];
        ansSeg[1][0] = ret1[1];
    }
    else{
        ansSeg[0][0] = ret1[1];
        ansSeg[1][0] = ret1[0];
    }

    while(true){
        int conditionToBreak = true;
        // decompose each part into half, then cyclic shift
        int len = segs.size();
        for (int i = 0; i < len; i++){
            int shift = segs[i].fi;
            int l = segs[i].se.fi, r = segs[i].se.se;
            if (l == r){
                continue;
            }
            else{
                conditionToBreak = false;
            }
            int mid = (l + r)/2;
            segs[i].se = {l, mid};
            segs.push_back({i, {mid+1, r}});
            for (int bi = 0; bi < b; bi++){
                ansSeg[bi].push_back(vector<int>());
            }
            // cyclic shift the second seg on askQuery
            vector<int> tmp = askQuery[0], tmp2;
            for (int i = mid+1; i <= r; i++){
                askQuery[0][i] = askQuery[b-1][i];
            }
            for (int i = 0; i < b-1; i++){
                // paste it in 
                tmp2 = askQuery[i+1];
                for (int j = mid+1; j <= r; j++){
                    askQuery[i+1][j] = tmp[j];
                }
                tmp = tmp2;
            }
        }
        
        // cannot decompose anymore, keep current answer
        if (conditionToBreak){
            break;
        }

        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << askQuery[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }

        vector<vector<int>> retMid = shuffle(askQuery), boxAns(b);
        // rebuild ansSeg
        int hasHead = false;
        for (int &ai: retMid[0]){
            if (ai == head){
                hasHead = true;
                break;
            }
        }
        if (hasHead){
            boxAns[0] = retMid[0];
            boxAns[1] = retMid[1];
        }
        else{
            boxAns[0] = retMid[1];
            boxAns[1] = retMid[0];
        }

        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << boxAns[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        
        // now that order of box is sorted, we will rebuild ansSeg
        vector<vector<vector<int>>> newAnsSeg(b, vector<vector<int>>(segs.size(), vector<int>()));
        for (int i = 0; i < segs.size(); i++){
            int shift = segs[i].fi;
            for (int bi = 0; bi < b; bi++){
                // shift = 
                int oldSeg = (shift == -1 ? i : shift);
                int oldBox = (shift == -1 ? bi : (bi-1+b)%b);
                for (int aOld: ansSeg[oldBox][oldSeg]){
                    for (int aAns: boxAns[bi]){
                        if (aOld == aAns){
                            newAnsSeg[bi][i].push_back(aOld);
                        }
                    }
                }
            }
        }

        ansSeg = newAnsSeg;
        // for (int i = 0; i < segs.size(); i++){
        //     cout << "segments: " << i << endl;
        //     for (int bi = 0; bi < b; bi++){
        //         cout << "box " << bi << ": " << endl;
        //         for (int &a: ansSeg[bi][i]){
        //             cout << a << ' ';
        //         }
        //         cout << endl;
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        // reset all shifts, as each one is stored in the correct ansSegs
        for (int i = 0; i < segs.size(); i++){
            segs[i].fi = -1;
        }
    }
    // build ans from askQuery, ansSeg and segs
    int len = segs.size();
    for (int i = 0; i < len; i++){
        // all segs are 1 len
        int l = segs[i].se.fi;
        for (int bi = 0; bi < b; bi++){
            ans[askQuery[bi][l]-1] = ansSeg[bi][i][0];
        }
    }
    // for (int i = 0; i < n; i++){
    //     cout << ans[i] << ' ';
    // }
    // cout << endl;
    return ans;
}

// sub3
// same thing as sub5 but no need to find first ans
vector<int> sub3(int n, int b, int k){
    vector<int> ans(n);
    vector<vector<int>> askQuery(b, vector<int>(k, 0)), ret1, ret2, ret3;
    
    int cnt = 1;
    for (int bi = 0; bi < b; bi++){
        for(int i = 0; i < k; i++){
            askQuery[bi][i] = cnt++;
        }
    }
    ret1 = shuffle(askQuery);
    flatten(ret1);

    vector<vector<vector<int>>> ansSeg(b, vector<vector<int>>(1, vector<int>()));
    vector<pair<int, pair<int, int>>> segs(1);

    for (int bi = 0; bi < b; bi++){
        segs[0] = {-1, {0, k-1}};
    }

    for (int bi = 0; bi < b; bi++){
        ansSeg[bi][0] = ret1[bi];
    }

    while(true){
        int conditionToBreak = true;
        // decompose each part into half, then cyclic shift
        int len = segs.size();
        for (int i = 0; i < len; i++){
            int shift = segs[i].fi;
            int l = segs[i].se.fi, r = segs[i].se.se;
            if (l == r){
                continue;
            }
            else{
                conditionToBreak = false;
            }
            int mid = (l + r)/2;
            segs[i].se = {l, mid};
            segs.push_back({i, {mid+1, r}});
            for (int bi = 0; bi < b; bi++){
                ansSeg[bi].push_back(vector<int>());
            }
            // cyclic shift the second seg on askQuery
            vector<int> tmp = askQuery[0], tmp2;
            for (int i = mid+1; i <= r; i++){
                askQuery[0][i] = askQuery[b-1][i];
            }
            for (int i = 0; i < b-1; i++){
                // paste it in 
                tmp2 = askQuery[i+1];
                for (int j = mid+1; j <= r; j++){
                    askQuery[i+1][j] = tmp[j];
                }
                tmp = tmp2;
            }
        }
        
        // cannot decompose anymore, keep current answer
        if (conditionToBreak){
            break;
        }

        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << askQuery[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }

        vector<vector<int>> boxAns = shuffle(askQuery);
        // rebuild ansSeg

        // for (int bi = 0; bi < b; bi++){
        //     for (int i = 0; i < k; i++){
        //         cout << boxAns[bi][i] << ' ';
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        
        // now that order of box is sorted, we will rebuild ansSeg
        vector<vector<vector<int>>> newAnsSeg(b, vector<vector<int>>(segs.size(), vector<int>()));
        for (int i = 0; i < segs.size(); i++){
            int shift = segs[i].fi;
            for (int bi = 0; bi < b; bi++){
                // shift = 
                int oldSeg = (shift == -1 ? i : shift);
                int oldBox = (shift == -1 ? bi : (bi-1+b)%b);
                for (int aOld: ansSeg[oldBox][oldSeg]){
                    for (int aAns: boxAns[bi]){
                        if (aOld == aAns){
                            newAnsSeg[bi][i].push_back(aOld);
                        }
                    }
                }
            }
        }

        ansSeg = newAnsSeg;
        // for (int i = 0; i < segs.size(); i++){
        //     cout << "segments: " << i << endl;
        //     for (int bi = 0; bi < b; bi++){
        //         cout << "box " << bi << ": " << endl;
        //         for (int &a: ansSeg[bi][i]){
        //             cout << a << ' ';
        //         }
        //         cout << endl;
        //     }
        //     cout << endl;
        // }
        // cout << endl;
        // reset all shifts, as each one is stored in the correct ansSegs
        for (int i = 0; i < segs.size(); i++){
            segs[i].fi = -1;
        }
    }
    // build ans from askQuery, ansSeg and segs
    int len = segs.size();
    for (int i = 0; i < len; i++){
        // all segs are 1 len
        int l = segs[i].se.fi;
        for (int bi = 0; bi < b; bi++){
            ans[askQuery[bi][l]-1] = ansSeg[bi][i][0];
        }
    }
    // for (int i = 0; i < n; i++){
    //     cout << ans[i] << ' ';
    // }
    // cout << endl;
    return ans;
}

vector<int> solve(int N, int B, int K, int Q, int ST) {
    if (ST == 2 || ST == 4){
        return sub4(N);
    }
    else if (ST == 3){
        return sub3(N, B, K);
    }
    else if (ST == 1 || ST == 5){
        return sub5(N, B, K);
    }
    return sub6(N, B, K);
}

컴파일 시 표준 에러 (stderr) 메시지

grader.cpp: In function 'std::vector<std::vector<int> > shuffle(std::vector<std::vector<int> >)':
grader.cpp:51:51: warning: 'void std::random_shuffle(_RAIter, _RAIter, _Generator&&) [with _RAIter = __gnu_cxx::__normal_iterator<int*, vector<int> >; _Generator = int (&)(int)]' is deprecated: use 'std::shuffle' instead [-Wdeprecated-declarations]
   51 |         for (int i = 0; i < B; i++) random_shuffle(packed_cards[i].begin(), packed_cards[i].end(), myrandom);
      |                                     ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13/algorithm:61,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:51,
                 from grader.cpp:3:
/usr/include/c++/13/bits/stl_algo.h:4620:5: note: declared here
 4620 |     random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
      |     ^~~~~~~~~~~~~~
grader.cpp:52:36: warning: 'void std::random_shuffle(_RAIter, _RAIter, _Generator&&) [with _RAIter = __gnu_cxx::__normal_iterator<vector<int>*, vector<vector<int> > >; _Generator = int (&)(int)]' is deprecated: use 'std::shuffle' instead [-Wdeprecated-declarations]
   52 |         if (ST != 3) random_shuffle(packed_cards.begin(), packed_cards.end(), myrandom);
      |                      ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/13/bits/stl_algo.h:4620:5: note: declared here
 4620 |     random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last,
      |     ^~~~~~~~~~~~~~
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…