| #include <iostream> |
| #include <vector> |
| #include <algorithm> |
| #include <map> |
| #include <tuple> |
|
|
| using namespace std; |
|
|
| |
| struct Edge { |
| int to; |
| int weight; |
| }; |
|
|
| |
| struct Node { |
| vector<Edge> out; |
| }; |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| int L, R; |
| if (!(cin >> L >> R)) return 0; |
|
|
| vector<Node> nodes; |
| |
| |
| |
| nodes.push_back(Node{}); |
|
|
| |
| |
| |
| |
| |
| vector<int> H(21); |
| H[0] = 0; |
| for (int i = 1; i <= 20; ++i) { |
| int idx = nodes.size(); |
| nodes.push_back(Node{}); |
| nodes[idx].out.push_back({H[i-1], 0}); |
| nodes[idx].out.push_back({H[i-1], 1}); |
| H[i] = idx; |
| } |
|
|
| |
| int start_node = nodes.size(); |
| nodes.push_back(Node{}); |
|
|
| |
| auto get_len = [](int x) { |
| if (x == 0) return 0; |
| int len = 0; |
| while ((1LL << len) <= x) len++; |
| return len; |
| }; |
|
|
| int l_len = get_len(L); |
| int r_len = get_len(R); |
|
|
| |
| |
| map<tuple<int, int, int>, int> memo; |
|
|
| |
| |
| |
| auto build_range = [&](auto&& self, int lower, int upper, int height) -> int { |
| |
| |
| long long range_size = 1LL << height; |
| if (lower == 0 && upper == range_size - 1) { |
| return H[height]; |
| } |
| |
| |
| if (height == 0) return H[0]; |
|
|
| |
| auto key = make_tuple(lower, upper, height); |
| if (memo.count(key)) return memo[key]; |
|
|
| |
| int curr = nodes.size(); |
| nodes.push_back(Node{}); |
| memo[key] = curr; |
| |
| long long half = 1LL << (height - 1); |
| |
| |
| |
| int l0 = max((long long)lower, 0LL); |
| int u0 = min((long long)upper, half - 1); |
| |
| if (l0 <= u0) { |
| |
| int child0 = self(self, l0, u0, height - 1); |
| nodes[curr].out.push_back({child0, 0}); |
| } |
| |
| |
| |
| |
| int l1 = max((long long)lower, half) - half; |
| int u1 = min((long long)upper, 2 * half - 1) - half; |
| |
| if (l1 <= u1) { |
| int child1 = self(self, l1, u1, height - 1); |
| nodes[curr].out.push_back({child1, 1}); |
| } |
| |
| return curr; |
| }; |
|
|
| |
| for (int len = l_len; len <= r_len; ++len) { |
| |
| long long min_val = 1LL << (len - 1); |
| long long max_val = (1LL << len) - 1; |
| |
| long long A = max((long long)L, min_val); |
| long long B = min((long long)R, max_val); |
| |
| if (A <= B) { |
| |
| |
| int suffix_height = len - 1; |
| |
| int lower = A - min_val; |
| int upper = B - min_val; |
| |
| |
| int target = build_range(build_range, lower, upper, suffix_height); |
| |
| |
| nodes[start_node].out.push_back({target, 1}); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| cout << nodes.size() << "\n"; |
| for (int i = 0; i < nodes.size(); ++i) { |
| cout << nodes[i].out.size(); |
| for (auto& edge : nodes[i].out) { |
| cout << " " << edge.to + 1 << " " << edge.weight; |
| } |
| cout << "\n"; |
| } |
|
|
| return 0; |
| } |