Submission #1050615

#TimeUsernameProblemLanguageResultExecution timeMemory
1050615That_SalamanderFlight to the Ford (BOI22_communication)C++17
0 / 100
2258 ms3256 KiB
#include <bits/stdc++.h>

#include "communication.h"

using namespace std;

int answer[4][4] = {{0, 0, 0, 0}, {0, 1, 1, 0}, {1, 0, 0, 1}, {1, 1, 1, 1}};

int corruptible(int* a, int* b, int size) {
    bool canCorrupt = true;
    for (int i = 0; i < size; i++) {
        if (a[i] != b[i]) {
            if (!canCorrupt) return false;
            canCorrupt = false;
        } else {
            canCorrupt = true;
        }
    }

    return true;
}

struct Tracker {
    vector<pair<int, int>> ranges;

    Tracker(int n) {
        ranges.emplace_back(1, n);
    }

    int totalLength() {
        int res = 0;
        for (auto& p: ranges) {
            res += p.second - p.first + 1;
        }
        return res;
    }

    int getIndex(int val) {
        int extra = 0;
        for (auto& p: ranges) {
            if (val >= p.first && val <= p.second) {
                return extra + (val - p.first);
            }
            extra += p.second - p.first + 1;
        }
        cerr << "ERROR" << endl;
        return 0;
    }

    int getElem(int idx) {
        for (auto& p: ranges) {
            int length = p.second - p.first + 1;
            if (idx < length) {
                return p.first + idx;
            } else {
                idx -= length;
            }
        }
        cerr << "ERROR" << endl;
        return 1;
    }

    void removeRange(int start, int end) {
        vector<pair<int, int>> res;
        for (auto& p: ranges) {
            if (p.second < start || p.first > end) {
                res.push_back(p);
            } else {
                if (start <= p.first && p.second <= end) continue;
                else if (start <= p.first) res.push_back({end + 1, p.second});
                else if (p.second <= end) res.push_back({p.first, start - 1});
                else {
                    res.push_back({p.first, start - 1});
                    res.push_back({end + 1, p.second});
                }
            }
        }

        ranges.swap(res);
    }

    void print() {
        for (auto& p: ranges) {
            cout << "[" << p.first << " " << p.second << "] ";
        }
        cout << endl;
    }
};

pair<int, int> sendNumber(int num) {
    int res[4];
    for (int i = 0; i < 4; i++) {
        res[i] = send(answer[num-1][i]);
    }

    int other = num;
    for (int i = 1; i <= 4; i++) {
        if (i == num) continue;
        if (corruptible(res, answer[i-1], 4)) {
            other = i;
            break;
        }
    }

    return {min(other, num), max(other, num)};
}

void encode(int n, int x) {
    Tracker tracker(n); 

    while (tracker.totalLength() > 2) {
        int currLength = tracker.totalLength();
        //cout << "Length = " << currLength << endl;
        int setLength = currLength / 4;

        int idx = tracker.getIndex(x);

        pair<int, int> recved = sendNumber(min(idx / setLength + 1, 4));

        for (int i = 4; i >= 1; i--) {
            int start = tracker.getElem(setLength * (i - 1));
            int end = tracker.getElem(i == 4 ? currLength - 1 : setLength * i - 1);
            
            if (i != recved.first && i != recved.second) {
                //cout << "Removing range " << start << " " << end << endl;
                tracker.removeRange(start, end);
            }
        }
        //tracker.print();
    }
}

pair<int, int> decode(int n) {
    Tracker tracker(n);

    while (tracker.totalLength() > 2) {
        int res[4];
        for (int i = 0; i < 4; i++) {
            res[i] = receive();
        }

        vector<int> nums;
        for (int i = 0; i < 4; i++) {
            if (corruptible(res, answer[i], 4)) {
                nums.push_back(i + 1);
            }
        }
        nums.push_back(nums[0]);

        int a = nums[0];
        int b = nums[1];

        int currLength = tracker.totalLength();
        int setLength = currLength / 4;

        for (int i = 4; i >= 1; i--) {
            int start = tracker.getElem(setLength * (i - 1));
            int end = tracker.getElem(i == 4 ? currLength - 1 : setLength * i - 1);
            
            if (i != a && i != b) {
                //cout << "Removing range " << start << " " << end << endl;
                tracker.removeRange(start, end);
            }
        }

        //tracker.print();
    }

    return {tracker.getElem(0), tracker.getElem(1)};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...