답안 #688573

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
688573 2023-01-27T18:14:51 Z nhphucqt CEOI16_icc (CEOI16_icc) C++17
100 / 100
122 ms 612 KB
#include <bits/stdc++.h>
#include "icc.h"

#define LOG2(n) (31 - __builtin_clz(n))
#define GETBIT(x,k) (((x)>>(k))&1)

using namespace std;

const int N = 107;
int fa[N];
int nTotal, nLef, nRig;
int total[N], lef[N], rig[N];
vector<int> comp[N];

int root (int x) {
    return fa[x] < 0 ? x : fa[x] = root(fa[x]);
}

void unite(int u, int v) {
    u = root(u);
    v = root(v);
    assert(u != v);
    if (fa[u] > fa[v]) {
        swap(u, v);
    }
    fa[u] += fa[v];
    fa[v] = u;
    for (int x : comp[v]) {
        comp[u].push_back(x);
    }
}

void makeQuery() {
    while (nLef > 1) {
        if (query((nLef+1)/2, nRig, lef, rig) == 1) {
            nLef = (nLef+1)/2;
        } else {
            int cLef = 0;
            for (int i = (nLef+1)/2; i < nLef; ++i) {
                lef[cLef++] = lef[i];
            }
            nLef = cLef;
        }
    }
    while (nRig > 1) {
        if (query(nLef, (nRig+1)/2, lef, rig) == 1) {
            nRig = (nRig+1)/2;
        } else {
            int cRig = 0;
            for (int i = (nRig+1)/2; i < nRig; ++i) {
                rig[cRig++] = rig[i];
            }
            nRig = cRig;
        }
    }
}

void run(int numNode) {
    memset(fa, -1, (numNode+1) * sizeof(int));
    for (int i = 1; i <= numNode; ++i) {
        comp[i].push_back(i);
    }
    int numComp = numNode;
    while (numComp-- > 1) {
        nTotal = 0;
        for (int i = 1; i <= numNode; ++i) {
            if (i == root(i)) {
                total[nTotal++] = i;
            }
        }
        // cerr << "Total: ";
        // for (int i = 0; i < nTotal; ++i) {
        //     cerr << total[i] << ' ';
        // }
        // cerr << '\n';
        int sumXor = 0;
        for (int j = 0; j <= LOG2(nTotal-1); ++j) {
            nLef = nRig = 0;
            for (int i = 0; i < nTotal; ++i) {
                if ((i>>j) & 1) {
                    for (int x : comp[total[i]]) {
                        lef[nLef++] = x;
                    }
                } else {
                    for (int x : comp[total[i]]) {
                        rig[nRig++] = x;
                    }
                }
            }
            sumXor ^= query(nLef, nRig, lef, rig)<<j;
        }
        int idx = 0, idy = 0;
        int pivot = LOG2(sumXor&(-sumXor));
        idx ^= 1<<pivot;
        for (int j = 0; j <= LOG2(nTotal-1); ++j) if (j != pivot) {
            if (GETBIT(sumXor,j)) {
                // suppose 1 is at x, 0 is at y
                nLef = nRig = 0;
                for (int i = 0; i < nTotal; ++i) {
                    if (GETBIT(i,pivot) && GETBIT(i,j)) {
                        for (int x : comp[total[i]]) {
                            lef[nLef++] = x;
                        }
                    } else if (!GETBIT(i,pivot) && !GETBIT(i,j)) {
                        for (int x : comp[total[i]]) {
                            rig[nRig++] = x;
                        }
                    }
                }
                if (query(nLef, nRig, lef, rig)) {
                    idx ^= 1<<j;
                } else {
                    idy ^= 1<<j;
                }
            } else {
                // suppose 0 is at x and y
                nLef = nRig = 0;
                for (int i = 0; i < nTotal; ++i) {
                    if (GETBIT(i,pivot) && !GETBIT(i,j)) {
                        for (int x : comp[total[i]]) {
                            lef[nLef++] = x;
                        }
                    } else if (!GETBIT(i,pivot) && !GETBIT(i,j)) {
                        for (int x : comp[total[i]]) {
                            rig[nRig++] = x;
                        }
                    }
                }
                if (!query(nLef, nRig, lef, rig)) {
                    idx ^= 1<<j;
                    idy ^= 1<<j;
                }
            }
        }
        nLef = nRig = 0;
        for (int u : comp[total[idx]]) {
            lef[nLef++] = u;
        }
        for (int u : comp[total[idy]]) {
            rig[nRig++] = u;
        }
        // cerr << "x, y : " << idx << ", " << idy << '\n';
        // cerr << "Lef : ";
        // for (int i = 0; i < nLef; ++i) {
        //     cerr << lef[i] << ' ';
        // }
        // cerr << '\n';
        // cerr << "Rig : ";
        // for (int i = 0; i < nRig; ++i) {
        //     cerr << rig[i] << ' ';
        // }
        // cerr << '\n';
        // cerr << "Query : " << query(nLef, nRig, lef, rig) << '\n';
        makeQuery();
        assert(nLef == 1 && nRig == 1);
        // cerr << "Set road: " << lef[0] << ' ' << rig[0] << '\n';
        setRoad(lef[0], rig[0]);
        unite(lef[0], rig[0]);
    }
}
# 결과 실행 시간 메모리 Grader output
1 Correct 6 ms 468 KB Ok! 117 queries used.
2 Correct 8 ms 596 KB Ok! 115 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 35 ms 484 KB Ok! 641 queries used.
2 Correct 32 ms 496 KB Ok! 540 queries used.
3 Correct 35 ms 468 KB Ok! 578 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 118 ms 468 KB Ok! 1573 queries used.
2 Correct 107 ms 484 KB Ok! 1337 queries used.
3 Correct 115 ms 612 KB Ok! 1609 queries used.
4 Correct 118 ms 480 KB Ok! 1549 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 115 ms 484 KB Ok! 1551 queries used.
2 Correct 122 ms 488 KB Ok! 1482 queries used.
3 Correct 110 ms 516 KB Ok! 1467 queries used.
4 Correct 113 ms 468 KB Ok! 1591 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 105 ms 488 KB Ok! 1373 queries used.
2 Correct 106 ms 480 KB Ok! 1388 queries used.
3 Correct 112 ms 488 KB Ok! 1405 queries used.
4 Correct 104 ms 488 KB Ok! 1443 queries used.
5 Correct 116 ms 488 KB Ok! 1593 queries used.
6 Correct 112 ms 480 KB Ok! 1593 queries used.
# 결과 실행 시간 메모리 Grader output
1 Correct 109 ms 548 KB Ok! 1429 queries used.
2 Correct 110 ms 484 KB Ok! 1374 queries used.