結果
問題 |
No.1694 ZerOne
|
ユーザー |
![]() |
提出日時 | 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 |
ソースコード
#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; }