結果

問題 No.1694 ZerOne
ユーザー qwewe
提出日時 2025-05-14 13:09:40
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 8,059 bytes
コンパイル時間 1,401 ms
コンパイル使用メモリ 101,256 KB
実行使用メモリ 121,420 KB
最終ジャッジ日時 2025-05-14 13:11:00
合計ジャッジ時間 4,660 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other TLE * 1 -- * 30
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <string>
#include <vector>
#include <set> // To store unique reachable strings
#include <queue> // For BFS queue
#include <map> // To map counts to substring locations
#include <vector> // To store list of locations
#include <utility> // For std::pair

int main() {
    // Use faster I/O
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    std::string S; // Input string
    std::cin >> S;

    std::set<std::string> reachable; // Set to store all unique strings reachable from S
    std::queue<std::string> q; // Queue for BFS traversal

    // Initialize BFS
    reachable.insert(S);
    q.push(S);

    int N = S.length(); // Length of the string

    // Start BFS
    while (!q.empty()) {
        std::string current_S = q.front(); // Get the current string to process
        q.pop(); // Remove it from the queue

        // Precompute prefix sums for the current string `current_S`
        // prefix_sums[i] stores the count of 0s (first) and 1s (second) in the prefix current_S[0...i-1]
        std::vector<std::pair<int, int>> prefix_sums(N + 1);
        prefix_sums[0] = {0, 0}; // Base case: empty prefix has zero 0s and 1s
        for (int i = 0; i < N; ++i) {
            prefix_sums[i+1] = prefix_sums[i]; // Copy counts from previous prefix
            if (current_S[i] == '0') {
                prefix_sums[i+1].first++; // Increment count of 0s
            } else {
                prefix_sums[i+1].second++; // Increment count of 1s
            }
        }

        // Create a map to store locations of all substrings, grouped by their (count0, count1)
        // Key: std::pair<int, int> representing the counts (number of 0s, number of 1s)
        // Value: std::vector<std::pair<int, int>> storing pairs of [L, R] indices (1-based) for substrings with these counts
        std::map<std::pair<int, int>, std::vector<std::pair<int, int>>> count_to_indices;
        
        // Iterate through all possible start and end indices to find all substrings
        for (int i = 0; i < N; ++i) { // Start index (0-based)
            for (int j = i; j < N; ++j) { // End index (0-based)
                int L = i + 1; // Convert to 1-based start index L
                int R = j + 1; // Convert to 1-based end index R
                
                // Calculate the counts of 0s and 1s for the substring S[L..R] using prefix sums
                // The counts for S[L..R] (which is S[L-1..R-1] in 0-based indexing) is P[R] - P[L-1]
                std::pair<int, int> counts = {prefix_sums[R].first - prefix_sums[L-1].first, prefix_sums[R].second - prefix_sums[L-1].second};
                
                // Store the location [L, R] associated with its counts
                // We only care about non-empty substrings. The loop condition i<=j ensures R>=L.
                 count_to_indices[counts].push_back({L, R});
            }
        }

        // Iterate through the map. For each distinct count vector, check pairs of substrings.
        for (auto const& [counts, locations] : count_to_indices) {
             // Skip counts (0,0) which correspond to empty substrings. This check is mostly for safety.
             if (counts.first == 0 && counts.second == 0) continue; 

            int k = locations.size(); // Number of substrings found with this count vector
            // If there are fewer than 2 substrings with these counts, we cannot perform a swap.
            if (k < 2) continue; 

            // Iterate through all distinct pairs of locations (i, j) for the current count vector
            for (int i = 0; i < k; ++i) {
                for (int j = i + 1; j < k; ++j) {
                    
                    // Consider the pair of substrings defined by locations[i] and locations[j]
                    // Let's test if locations[i] can be substring t and locations[j] can be substring u
                    int Lt1 = locations[i].first;
                    int Rt1 = locations[i].second;
                    int Lu1 = locations[j].first;
                    int Ru1 = locations[j].second;

                    // Check the non-overlapping condition: t must end before u begins (Rt < Lu)
                    if (Rt1 < Lu1) { 
                        // Extract the actual substrings t and u from current_S
                        // std::string::substr uses 0-based index and length
                        // Substring S[L..R] corresponds to indices L-1 to R-1
                        // Length is R - L + 1
                        std::string t = current_S.substr(Lt1 - 1, Rt1 - Lt1 + 1);
                        std::string u = current_S.substr(Lu1 - 1, Ru1 - Lu1 + 1);
                        
                        // Construct the new string `next_S` by swapping t and u: S = A t B u C -> S' = A u B t C
                        std::string next_S = "";
                        // Part A: S[1..Lt1-1] => indices 0 to Lt1-2
                        if (Lt1 > 1) next_S += current_S.substr(0, Lt1 - 1); 
                        // Part u
                        next_S += u;                                        
                        // Part B: S[Rt1+1..Lu1-1] => indices Rt1 to Lu1-2. Exists if Lu1-1 >= Rt1+1 => Lu1 > Rt1+1
                        if (Lu1 > Rt1 + 1) next_S += current_S.substr(Rt1, Lu1 - 1 - Rt1); 
                        // Part t
                        next_S += t;                                        
                        // Part C: S[Ru1+1..N] => indices Ru1 to N-1. Exists if N > Ru1
                        if (N > Ru1) next_S += current_S.substr(Ru1);         

                        // If the generated string `next_S` is new (not visited before)
                        if (reachable.find(next_S) == reachable.end()) {
                            reachable.insert(next_S); // Add it to the set of reachable strings
                            q.push(next_S); // Add it to the BFS queue to explore further
                        }
                    }

                    // Now test if locations[j] can be substring t and locations[i] can be substring u
                    // This is needed because the order in the `locations` vector might not correspond to string order
                    int Lt2 = locations[j].first;
                    int Rt2 = locations[j].second;
                    int Lu2 = locations[i].first;
                    int Ru2 = locations[i].second;

                    // Check the non-overlapping condition: t must end before u begins (Rt < Lu)
                    if (Rt2 < Lu2) {
                        // Extract substrings t and u
                         std::string t = current_S.substr(Lt2 - 1, Rt2 - Lt2 + 1);
                         std::string u = current_S.substr(Lu2 - 1, Ru2 - Lu2 + 1);
                            
                         // Construct the new string S' = A u B t C
                         std::string next_S = "";
                         // Part A: S[1..Lt2-1]
                         if (Lt2 > 1) next_S += current_S.substr(0, Lt2 - 1); 
                         // Part u
                         next_S += u;                                        
                         // Part B: S[Rt2+1..Lu2-1]
                         if (Lu2 > Rt2 + 1) next_S += current_S.substr(Rt2, Lu2 - 1 - Rt2); 
                         // Part t
                         next_S += t;                                        
                         // Part C: S[Ru2+1..N]
                         if (N > Ru2) next_S += current_S.substr(Ru2);         

                         // If the generated string `next_S` is new
                         if (reachable.find(next_S) == reachable.end()) {
                             reachable.insert(next_S); // Add to set
                             q.push(next_S); // Add to queue
                         }
                    }
                }
            }
        }
    }

    // After BFS completes, the size of the `reachable` set is the answer
    std::cout << reachable.size() << std::endl;

    return 0;
}
0