Submission #1296313

#TimeUsernameProblemLanguageResultExecution timeMemory
1296313NotLinuxMessage (IOI24_message)C++20
0 / 100
178 ms800 KiB
#include "message.h"
#include <bits/stdc++.h>

using namespace std;

void send_message(vector<bool> M, vector<bool> C) {
    int S = M.size();
    int msg_ptr = 0;
    
    // We assume standard packet size of 31.
    // We limit our search to the first 16 bits [0..15].
    // Due to Pigeonhole Principle (31 total, 16 safe, 15 Cleo), 
    // there MUST be at least one safe bit in range [0..15].
    
    int target_safe = -1;
    for(int i = 0; i <= 15; i++) {
        if(!C[i]) {
            target_safe = i;
            break;
        }
    }
    
    // ---------------------------------------------------------
    // PHASE 1: Binary Search (4 iterations)
    // ---------------------------------------------------------
    // Search Range starts at [0, 15]
    int bs_L = 0;
    int bs_R = 15;
    
    for (int iter = 0; iter < 4; iter++) {
        vector<bool> packet(31, 0);
        int mid = bs_L + (bs_R - bs_L) / 2;
        
        // Define halves
        // Left: [bs_L, mid], Right: [mid+1, bs_R]
        
        // Sender Logic: 
        // If target is in Left, light up SAFE bits in Left.
        // If target is in Right, light up SAFE bits in Right.
        bool go_right = (target_safe > mid);
        
        for (int i = 0; i < 31; i++) {
            bool in_current_bs_range = (i >= bs_L && i <= bs_R);
            
            if (in_current_bs_range) {
                // We are inside the active comparison zone.
                // We only light up the side where the target is.
                bool in_left_half = (i <= mid);
                bool in_right_half = (i > mid);
                
                if (!go_right && in_left_half) {
                    // Target is left, we are in left. Send 1 if safe.
                    if (!C[i]) packet[i] = 1;
                } else if (go_right && in_right_half) {
                    // Target is right, we are in right. Send 1 if safe.
                    if (!C[i]) packet[i] = 1;
                }
                // Else: we are in the "wrong" half or it's a Cleo bit. 
                // We send 0 (Sender preference).
            } else {
                // "Use every bit that is both safe and not in the binary search range"
                // This includes bits 16-30 and bits discarded in previous BS steps.
                if (!C[i] && msg_ptr < S) {
                    packet[i] = M[msg_ptr++];
                }
            }
        }
        
        send_packet(packet);
        
        // Update Sender's view of BS state for next iteration
        if (!go_right) bs_R = mid;
        else bs_L = mid + 1;
    }

    // ---------------------------------------------------------
    // PHASE 2: Map Discovery (30 Packets)
    // ---------------------------------------------------------
    // target_safe tells us the state of the other 30 bits.
    
    vector<int> map_targets;
    for(int i=0; i<31; i++) {
        if(i != target_safe) map_targets.push_back(i);
    }
    
    for (int i = 0; i < 30; i++) {
        vector<bool> packet(31, 0);
        int index_to_report = map_targets[i];
        
        // Signaling bit
        packet[target_safe] = !C[index_to_report]; // 1 if Safe, 0 if Corrupt
        
        // Message bits (All other safe bits)
        for (int j = 0; j < 31; j++) {
            if (j == target_safe) continue;
            
            if (!C[j] && msg_ptr < S) {
                packet[j] = M[msg_ptr++];
            }
        }
        send_packet(packet);
    }
    
    // ---------------------------------------------------------
    // PHASE 3: Flush Remaining Message
    // ---------------------------------------------------------
    while (msg_ptr < S) {
        vector<bool> packet(31, 0);
        for(int j=0; j<31; j++) {
            if (!C[j] && msg_ptr < S) {
                packet[j] = M[msg_ptr++];
            }
        }
        send_packet(packet);
    }
}

vector<bool> receive_message(vector<vector<bool>> R) {
    // We need to look back in time, so we process R in multiple passes.
    vector<bool> M;
    
    // ---------------------------------------------------------
    // Step 1: Replay Binary Search to find the Safe Bit
    // ---------------------------------------------------------
    int bs_L = 0;
    int bs_R = 15;
    
    for (int iter = 0; iter < 4; iter++) {
        int mid = bs_L + (bs_R - bs_L) / 2;
        
        // Count 1s in the Left Half vs Right Half
        int sum_left = 0;
        int sum_right = 0;
        
        for (int i = bs_L; i <= mid; i++) {
            if (R[iter][i]) sum_left++;
        }
        for (int i = mid + 1; i <= bs_R; i++) {
            if (R[iter][i]) sum_right++;
        }
        
        // "See which one has the majority and go into that part"
        if (sum_left > sum_right) {
            bs_R = mid;
        } else {
            bs_L = mid + 1;
        }
    }
    
    int primary_safe = bs_L; 
    
    // ---------------------------------------------------------
    // Step 2: Build the Safe Map
    // ---------------------------------------------------------
    vector<bool> is_safe(31, false);
    is_safe[primary_safe] = true;
    
    vector<int> map_targets;
    for(int i=0; i<31; i++) {
        if(i != primary_safe) map_targets.push_back(i);
    }
    
    for (int i = 0; i < 30; i++) {
        // Read the signal from the known safe bit
        bool info = R[4 + i][primary_safe];
        int index_being_reported = map_targets[i];
        is_safe[index_being_reported] = info;
    }
    
    // ---------------------------------------------------------
    // Step 3: Extract Message (Time Travel)
    // ---------------------------------------------------------
    
    // 3a. From BS Phase (Packets 0-3)
    bs_L = 0; bs_R = 15;
    for (int iter = 0; iter < 4; iter++) {
        // Extract message from bits NOT in current BS range
        for (int j = 0; j < 31; j++) {
            bool in_range = (j >= bs_L && j <= bs_R);
            if (!in_range && is_safe[j]) {
                M.push_back(R[iter][j]);
            }
        }
        
        // Re-calculate BS step to know the range for the *next* iteration
        int mid = bs_L + (bs_R - bs_L) / 2;
        int sum_left = 0; 
        int sum_right = 0;
        for (int i = bs_L; i <= mid; i++) if (R[iter][i]) sum_left++;
        for (int i = mid + 1; i <= bs_R; i++) if (R[iter][i]) sum_right++;
        
        if (sum_left > sum_right) bs_R = mid;
        else bs_L = mid + 1;
    }
    
    // 3b. From Map Phase (Packets 4-33)
    for (int i = 0; i < 30; i++) {
        for (int j = 0; j < 31; j++) {
            if (j == primary_safe) continue; // This was used for signaling
            if (is_safe[j]) {
                M.push_back(R[4 + i][j]);
            }
        }
    }
    
    // 3c. From Flush Phase (Packets 34+)
    for (int p = 34; p < R.size(); p++) {
        for (int j = 0; j < 31; j++) {
            if (is_safe[j]) {
                M.push_back(R[p][j]);
            }
        }
    }
    
    return M;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...