File size: 2,290 Bytes
1fd0050
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <map>
#include <tuple>

using namespace std;

using ll = long long;

struct Edge {
    int to;
    int weight;
};

vector<vector<Edge>> adj;
int n_nodes;

int newNode() {
    n_nodes++;
    adj.resize(n_nodes + 1);
    return n_nodes;
}

map<tuple<int, ll, ll>, int> memo;

int gen(int len, ll l, ll r) {
    if (l > r) {
        return 2;
    }
    if (len == 0) {
        return 2;
    }
    if (memo.count({len, l, r})) {
        return memo.at({len, l, r});
    }

    int u = newNode();
    memo[{len, l, r}] = u;

    ll p_val = 1LL << (len - 1);

    if (r < p_val) { // All numbers' MSB is 0
        int next_node = gen(len - 1, l, r);
        adj[u].push_back({next_node, 0});
    } else if (l >= p_val) { // All numbers' MSB is 1
        int next_node = gen(len - 1, l - p_val, r - p_val);
        adj[u].push_back({next_node, 1});
    } else { // Divergence
        // Range [l, p_val - 1] starts with 0
        int next_l = gen(len - 1, l, p_val - 1);
        adj[u].push_back({next_l, 0});

        // Range [p_val, r] starts with 1
        int next_r = gen(len - 1, 0, r - p_val);
        adj[u].push_back({next_r, 1});
    }
    return u;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    ll L, R;
    cin >> L >> R;

    n_nodes = 2; // 1: start, 2: end
    adj.resize(n_nodes + 1);

    if (L == 1) {
        adj[1].push_back({2, 1});
        L = 2;
    }

    if (L <= R) {
        int lenL = floor(log2(L)) + 1;
        int lenR = floor(log2(R)) + 1;

        for (int k = lenL; k <= lenR; ++k) {
            ll low_k = (k == lenL) ? L : (1LL << (k - 1));
            ll high_k = (k == lenR) ? R : (1LL << k) - 1;

            if (low_k > high_k) continue;

            ll suffix_l = low_k - (1LL << (k - 1));
            ll suffix_r = high_k - (1LL << (k - 1));

            int suffix_start_node = gen(k - 1, suffix_l, suffix_r);
            adj[1].push_back({suffix_start_node, 1});
        }
    }

    cout << n_nodes << endl;
    for (int i = 1; i <= n_nodes; ++i) {
        cout << adj[i].size();
        for (const auto& edge : adj[i]) {
            cout << " " << edge.to << " " << edge.weight;
        }
        cout << endl;
    }

    return 0;
}