IOI 2013
IOI 2013

Cave

There is a cave with N doors (numbered 0 to N-1) and N switches (numbered 0 to N-1). Each switch controls exactly one door (a permutation), and each switch has a correct position (0 or 1) that opens its corresponding...

Updated May 21, 2026
Track IOI
Year 2013
Statement Rendered from TeX
TeXC++Rendered statement

Problem Statement

Rendered from the "Problem Summary" section in the LaTeX write-up.

There is a cave with $N$ doors (numbered $0$ to $N-1$) and $N$ switches (numbered $0$ to $N-1$). Each switch controls exactly one door (a permutation), and each switch has a correct position (0 or 1) that opens its corresponding door. You can query the system by providing a switch configuration (array of 0s and 1s) and observing which door is the first closed door (or all open). Determine the mapping (which switch controls which door) and the correct position for each switch, using at most $70000$ queries.

Editorial

The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.

Solution Approach

Use binary search to determine each switch-door mapping:

  1. Process doors in order $0, 1, \ldots, N-1$.

  2. For door $d$, we know the correct settings for switches controlling doors $0, \ldots, d-1$ (so those doors are open). The remaining switches are ``unknown.''

  3. Binary search on the set of unknown switches to find which one controls door $d$:

    • Set the known switches to their correct values (doors 0..d-1 open).

    • For unknown switches: set the first half to 0 and the rest to 1 (or vice versa).

    • Query. If door $d$ is open, the controlling switch is in one half; if closed, it's in the other half.

    • Recurse on the correct half until one switch remains.

    • Then determine the correct position for that switch by toggling it. enumerate

      Complexity

      • Queries: $O(N \log N)$ --- for each of $N$ doors, $O(\log N)$ binary search queries.

      • For $N = 5000$: $5000 \times 13 \approx 65000 < 70000$. Fits within budget.

      C++ Solution

      #include <bits/stdc++.h>
      using namespace std;
      
      // Grader functions:
      // int tryCombination(int S[]) - returns first closed door, or -1 if all open
      // void answer(int S[], int D[]) - report solution
      // S[i] = correct position (0/1) for switch i
      // D[i] = which door switch i controls
      
      int tryCombination(int S[]);
      void answer(int S[], int D[]);
      
      void exploreCave(int N){
          vector<int> switchPos(N, -1);  // correct position for each switch
          vector<int> switchDoor(N, -1); // which door each switch controls
          vector<bool> determined(N, false); // whether switch i is determined
      
          for(int door = 0; door < N; door++){
              // Collect undetermined switches
              vector<int> unknown;
              for(int i = 0; i < N; i++){
                  if(!determined[i]) unknown.push_back(i);
              }
      
              // First, determine the "test value" for unknown switches
              // that makes door 'door' close (so we can detect it).
              // Try setting all unknown switches to 0:
              int *S = new int[N];
              for(int i = 0; i < N; i++){
                  if(determined[i]){
                      S[i] = switchPos[i]; // known correct value
                  } else {
                      S[i] = 0;
                  }
              }
              int result = tryCombination(S);
              int testVal; // the value for unknown switches that closes door 'door'
              if(result == door){
                  // All unknowns at 0 -> door is closed
                  // So the controlling switch's correct value is 1 (currently at 0 = wrong)
                  testVal = 0; // setting unknown to 0 closes the door
              } else {
                  // Door is open with all unknowns at 0
                  // So correct value is 0 for the controlling switch
                  // Set unknowns to 1 to close it
                  testVal = 1;
              }
      
              // Binary search on unknown switches
              int lo = 0, hi = (int)unknown.size() - 1;
              while(lo < hi){
                  int mid = (lo + hi) / 2;
                  // Set switches unknown[lo..mid] to testVal, rest to 1-testVal
                  for(int i = 0; i < N; i++){
                      if(determined[i]){
                          S[i] = switchPos[i];
                      } else {
                          S[i] = 1 - testVal; // default: opposite of testVal
                      }
                  }
                  for(int i = lo; i <= mid; i++){
                      S[unknown[i]] = testVal;
                  }
      
                  result = tryCombination(S);
                  if(result == door){
                      // The controlling switch is in [lo..mid] (with testVal, door closes)
                      hi = mid;
                  } else {
                      // Door is open -> controlling switch NOT in [lo..mid]
                      lo = mid + 1;
                  }
              }
      
              // Switch unknown[lo] controls door 'door'
              int sw = unknown[lo];
              switchDoor[sw] = door;
              switchPos[sw] = 1 - testVal; // testVal closes it, so correct = opposite
              determined[sw] = true;
      
              delete[] S;
          }
      
          int *S = new int[N], *D = new int[N];
          for(int i = 0; i < N; i++){
              S[i] = switchPos[i];
              D[i] = switchDoor[i];
          }
          answer(S, D);
          delete[] S; delete[] D;
      }
      
      int main(){
          int N;
          cin >> N;
          exploreCave(N);
          return 0;
      }
      
      int tryCombination(int S[]){ return -1; }
      void answer(int S[], int D[]){}

Code

C++ solution used for this page.

C++

Clean code view with a raw-file link when you want the original source.

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

// Grader functions:
// int tryCombination(int S[]) - returns first closed door, or -1 if all open
// void answer(int S[], int D[]) - report solution
// S[i] = correct position (0/1) for switch i
// D[i] = which door switch i controls

int tryCombination(int S[]);
void answer(int S[], int D[]);

void exploreCave(int N){
    vector<int> switchPos(N, -1);  // correct position for each switch
    vector<int> switchDoor(N, -1); // which door each switch controls
    vector<bool> determined(N, false); // whether switch i is determined

    for(int door = 0; door < N; door++){
        // Collect undetermined switches
        vector<int> unknown;
        for(int i = 0; i < N; i++){
            if(!determined[i]) unknown.push_back(i);
        }

        // First, determine the "test value" for unknown switches
        // that makes door 'door' close (so we can detect it).
        // Try setting all unknown switches to 0:
        int *S = new int[N];
        for(int i = 0; i < N; i++){
            if(determined[i]){
                S[i] = switchPos[i]; // known correct value
            } else {
                S[i] = 0;
            }
        }
        int result = tryCombination(S);
        int testVal; // the value for unknown switches that closes door 'door'
        if(result == door){
            // All unknowns at 0 -> door is closed
            // So the controlling switch's correct value is 1 (currently at 0 = wrong)
            testVal = 0; // setting unknown to 0 closes the door
        } else {
            // Door is open with all unknowns at 0
            // So correct value is 0 for the controlling switch
            // Set unknowns to 1 to close it
            testVal = 1;
        }

        // Binary search on unknown switches
        int lo = 0, hi = (int)unknown.size() - 1;
        while(lo < hi){
            int mid = (lo + hi) / 2;
            // Set switches unknown[lo..mid] to testVal, rest to 1-testVal
            for(int i = 0; i < N; i++){
                if(determined[i]){
                    S[i] = switchPos[i];
                } else {
                    S[i] = 1 - testVal; // default: opposite of testVal
                }
            }
            for(int i = lo; i <= mid; i++){
                S[unknown[i]] = testVal;
            }

            result = tryCombination(S);
            if(result == door){
                // The controlling switch is in [lo..mid] (with testVal, door closes)
                hi = mid;
            } else {
                // Door is open -> controlling switch NOT in [lo..mid]
                lo = mid + 1;
            }
        }

        // Switch unknown[lo] controls door 'door'
        int sw = unknown[lo];
        switchDoor[sw] = door;
        switchPos[sw] = 1 - testVal; // testVal closes it, so correct = opposite
        determined[sw] = true;

        delete[] S;
    }

    int *S = new int[N], *D = new int[N];
    for(int i = 0; i < N; i++){
        S[i] = switchPos[i];
        D[i] = switchDoor[i];
    }
    answer(S, D);
    delete[] S; delete[] D;
}

int main(){
    int N;
    cin >> N;
    exploreCave(N);
    return 0;
}

int tryCombination(int S[]){ return -1; }
void answer(int S[], int D[]){}

Source Files and Assets

Raw files are still available here when you want the original TeX, C++, or statement assets.

Show raw files