All IOI entries
Competitive Programming

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...

Source sync Apr 19, 2026
Track IOI
Year 2013
Files TeX and C++
Folder competitive_programming/ioi/2013/cave
IOI2013TeXC++

Source-first archive entry

This page is built from the copied files in competitive_programming/ioi/2013/cave. Edit competitive_programming/ioi/2013/cave/solution.tex to update the written solution and competitive_programming/ioi/2013/cave/solution.cpp to update the implementation.

The website does not replace those files with hand-maintained HTML. It reads the copied source tree during the build and exposes the exact files below.

Problem Statement

Rendered from the "Problem Summary" section inside solution.tex because this entry has no separate statement file.

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

Rendered from the copied solution.tex file. The original TeX source remains available below.

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

Exact copied C++ implementation from solution.cpp.

C++ competitive_programming/ioi/2013/cave/solution.cpp

Exact copied implementation 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

Exact copied source-of-truth files. Edit solution.tex for the write-up and solution.cpp for the implementation.

TeX write-up competitive_programming/ioi/2013/cave/solution.tex

Exact copied write-up source.

Raw file
\documentclass[11pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[margin=1in]{geometry}
\usepackage{amsmath,amssymb,amsthm}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{hyperref}

\lstset{
  language=C++,
  basicstyle=\ttfamily\small,
  keywordstyle=\color{blue}\bfseries,
  commentstyle=\color{green!60!black},
  stringstyle=\color{red!70!black},
  numbers=left,
  numberstyle=\tiny\color{gray},
  breaklines=true,
  frame=single,
  tabsize=4,
  showstringspaces=false
}

\title{IOI 2013 -- Cave}
\author{Solution}
\date{}

\begin{document}
\maketitle

\section{Problem Summary}
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.

\section{Solution Approach}
Use binary search to determine each switch-door mapping:

\begin{enumerate}
    \item Process doors in order $0, 1, \ldots, N-1$.
    \item 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.''
    \item Binary search on the set of unknown switches to find which one controls door $d$:
    \begin{itemize}
        \item Set the known switches to their correct values (doors 0..d-1 open).
        \item For unknown switches: set the first half to 0 and the rest to 1 (or vice versa).
        \item Query. If door $d$ is open, the controlling switch is in one half; if closed, it's in the other half.
        \item Recurse on the correct half until one switch remains.
    \end{itemize}
    \item Then determine the correct position for that switch by toggling it.
\end{enumerate}

\section{Complexity}
\begin{itemize}
    \item \textbf{Queries:} $O(N \log N)$ --- for each of $N$ doors, $O(\log N)$ binary search queries.
    \item For $N = 5000$: $5000 \times 13 \approx 65000 < 70000$. Fits within budget.
\end{itemize}

\section{C++ Solution}
\begin{lstlisting}
#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[]){}
\end{lstlisting}

\end{document}