| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| struct Graph { |
| vector<vector<pair<int,int>>> adj; |
| Graph() { adj.resize(1); } |
| int new_node() { |
| adj.emplace_back(); |
| return (int)adj.size() - 1; |
| } |
| void add_edge(int u, int v, int w) { |
| adj[u].push_back({v, w}); |
| } |
| int size() const { return (int)adj.size() - 1; } |
| }; |
|
|
| static Graph G; |
| static int S, T; |
|
|
| static vector<int> Lbits, Rbits; |
| static int lenL, lenR; |
|
|
| static vector<int> freeNode; |
| static vector<int> lowNode; |
| static vector<int> upNode; |
| static vector<int> bothNode; |
|
|
| int getFree(int rem) { |
| if (rem == 0) return T; |
| if (rem < (int)freeNode.size() && freeNode[rem] != 0) return freeNode[rem]; |
| int needSize = rem + 1; |
| if ((int)freeNode.size() < needSize) freeNode.resize(needSize, 0); |
| int id = G.new_node(); |
| freeNode[rem] = id; |
| int to = getFree(rem - 1); |
| G.add_edge(id, to, 0); |
| G.add_edge(id, to, 1); |
| return id; |
| } |
|
|
| int getLower(int pos) { |
| if (pos >= lenL) return T; |
| if (lowNode[pos] != 0) return lowNode[pos]; |
| int id = G.new_node(); |
| lowNode[pos] = id; |
| int b = Lbits[pos]; |
| if (b == 0) { |
| |
| int to_tight = getLower(pos + 1); |
| G.add_edge(id, to_tight, 0); |
| |
| int rem = lenL - pos - 1; |
| int to_free = getFree(rem); |
| G.add_edge(id, to_free, 1); |
| } else { |
| int to_tight = getLower(pos + 1); |
| G.add_edge(id, to_tight, 1); |
| } |
| return id; |
| } |
|
|
| int getUpper(int pos) { |
| if (pos >= lenR) return T; |
| if (upNode[pos] != 0) return upNode[pos]; |
| int id = G.new_node(); |
| upNode[pos] = id; |
| int b = Rbits[pos]; |
| if (b == 1) { |
| |
| int to_tight = getUpper(pos + 1); |
| G.add_edge(id, to_tight, 1); |
| |
| int rem = lenR - pos - 1; |
| int to_free = getFree(rem); |
| G.add_edge(id, to_free, 0); |
| } else { |
| int to_tight = getUpper(pos + 1); |
| G.add_edge(id, to_tight, 0); |
| } |
| return id; |
| } |
|
|
| int getBoth(int pos) { |
| int len = lenR; |
| if (pos >= len) return T; |
| if (bothNode[pos] != 0) return bothNode[pos]; |
| int id = G.new_node(); |
| bothNode[pos] = id; |
| int lb = Lbits[pos], ub = Rbits[pos]; |
| if (lb == ub) { |
| int to = getBoth(pos + 1); |
| G.add_edge(id, to, lb); |
| } else { |
| int to_low = getLower(pos + 1); |
| int to_up = getUpper(pos + 1); |
| G.add_edge(id, to_low, 0); |
| G.add_edge(id, to_up, 1); |
| } |
| return id; |
| } |
|
|
| vector<int> toBitsMSB(int x) { |
| vector<int> b; |
| while (x > 0) { |
| b.push_back(x & 1); |
| x >>= 1; |
| } |
| reverse(b.begin(), b.end()); |
| if (b.empty()) b.push_back(0); |
| return b; |
| } |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| int L, R; |
| if (!(cin >> L >> R)) return 0; |
|
|
| Lbits = toBitsMSB(L); |
| Rbits = toBitsMSB(R); |
| lenL = (int)Lbits.size(); |
| lenR = (int)Rbits.size(); |
|
|
| |
| S = G.new_node(); |
| T = G.new_node(); |
|
|
| |
| freeNode.resize(lenR + 1, 0); |
| lowNode.assign(lenL + 1, 0); |
| upNode.assign(lenR + 1, 0); |
| if (lenL == lenR) bothNode.assign(lenR + 1, 0); |
|
|
| |
| |
| if (lenL == lenR) { |
| int to = getBoth(1); |
| G.add_edge(S, to, 1); |
| } else { |
| |
| int toLow = getLower(1); |
| G.add_edge(S, toLow, 1); |
|
|
| |
| for (int len = lenL + 1; len <= lenR - 1; ++len) { |
| int toFree = getFree(len - 1); |
| G.add_edge(S, toFree, 1); |
| } |
|
|
| |
| int toUp = getUpper(1); |
| G.add_edge(S, toUp, 1); |
| } |
|
|
| |
| int n = G.size(); |
| cout << n << "\n"; |
| for (int i = 1; i <= n; ++i) { |
| cout << (int)G.adj[i].size(); |
| for (auto &e : G.adj[i]) { |
| cout << " " << e.first << " " << e.second; |
| } |
| cout << "\n"; |
| } |
| return 0; |
| } |