Submission #1244767

#TimeUsernameProblemLanguageResultExecution timeMemory
1244767matanChoreography (IOI23_choreography)C++17
19 / 100
1094 ms7096 KiB
#include "choreography.h" #include <vector> // Global variables to hold the state using dual array approach int N_dancers; std::vector<int> initial_p; // initial_p[initial_pos] = dancer_id (kept for compatibility) std::vector<int> initial_pos; // initial_pos[dancer_id] = initial_pos (kept for compatibility) // Dual array representation: std::vector<int> pos_dancers; // pos_dancers[dancer] = position (where is dancer D?) std::vector<int> pos_positions; // pos_positions[position] = dancer (who is at position P?) int shift_s; // Global shift for lazy evaluation // Helper to get actual position with shift applied int actual_position(int base_pos) { return (base_pos + shift_s + N_dancers) % N_dancers; } // Helper to get actual dancer at position with shift applied int actual_dancer_at(int pos) { int base_pos = (pos - shift_s + N_dancers) % N_dancers; return pos_positions[base_pos]; } // Initializes the state. void init(int N, std::vector<int> P) { N_dancers = N; initial_p.resize(N); initial_pos.resize(N); pos_dancers.resize(N); pos_positions.resize(N); for (int i = 0; i < N; ++i) { initial_p[i] = P[i]; initial_pos[P[i]] = i; } // Initialize dual arrays for (int i = 0; i < N; ++i) { int dancer = P[i]; pos_positions[i] = dancer; // Position i has dancer pos_dancers[dancer] = i; // Dancer is at position i } shift_s = 0; } // Adds a move of type 1 (move right by K). This is O(1). void move_right(int K) { shift_s = (shift_s + K) % N_dancers; } // Adds a move of type 2 (move left by K). This is O(1). void move_left(int K) { shift_s = (shift_s - K + N_dancers) % N_dancers; } // Helper function to "bake" the current shift into both arrays void bake_shift() { if (shift_s == 0) return; // No need to bake if there's no shift std::vector<int> new_pos_dancers(N_dancers); std::vector<int> new_pos_positions(N_dancers); // Bake shift into pos_dancers for (int d = 0; d < N_dancers; ++d) { new_pos_dancers[d] = actual_position(pos_dancers[d]); } // Bake shift into pos_positions for (int p = 0; p < N_dancers; ++p) { new_pos_positions[p] = actual_dancer_at(p); } pos_dancers = new_pos_dancers; pos_positions = new_pos_positions; shift_s = 0; // Reset the shift after baking } // Adds a move of type 3 (swap adjacent). This is O(N). void swap_places() { // First, bake the current shift into both arrays bake_shift(); // Apply swap to both arrays consistently for (int i = 0; i < N_dancers; i += 2) { if (i + 1 < N_dancers) { // Swap positions i and i+1 int dancer_at_i = pos_positions[i]; int dancer_at_i1 = pos_positions[i + 1]; // Update pos_positions pos_positions[i] = dancer_at_i1; pos_positions[i + 1] = dancer_at_i; // Update pos_dancers pos_dancers[dancer_at_i] = i + 1; pos_dancers[dancer_at_i1] = i; } } } // Adds a move of type 4 (move around). This is O(N) when there's a shift, O(1) when no shift. void move_around() { // We need to bake the shift first, then apply move_around logic bake_shift(); // Now that shift is baked, we can apply the move_around rule: // For each dancer D, new position = pos_positions[D] std::vector<int> new_pos_dancers(N_dancers); for (int dancer = 0; dancer < N_dancers; ++dancer) { new_pos_dancers[dancer] = pos_positions[dancer]; } // Update pos_positions to reflect the new arrangement std::vector<int> new_pos_positions(N_dancers); for (int dancer = 0; dancer < N_dancers; ++dancer) { int new_pos = new_pos_dancers[dancer]; new_pos_positions[new_pos] = dancer; } pos_dancers = new_pos_dancers; pos_positions = new_pos_positions; // shift_s is already 0 from bake_shift() } // Returns the current position of dancer D. This is O(1). int get_position(int D) { return actual_position(pos_dancers[D]); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...