#include #include #include using namespace std; const int MAXN = 200000; int treeSize; int queriesNumber; struct Node { int l, r; long long add, colors; } tree[MAXN * 4]; void init (int pos, int l, int r) { tree[pos].l = l; tree[pos].r = r; if (l < r) { init(pos + pos, l, (l + r) / 2); init(pos + pos + 1, (l + r) / 2 + 1, r); } } void push (int pos) { tree[pos].colors = tree[pos].add; if (tree[pos].l == tree[pos].r) return ; tree[pos + pos].add = tree[pos].add; tree[pos + pos + 1].add = tree[pos].add; tree[pos].add = 0; } void modify (int pos, int l, int r, long long tag) { if (tree[pos].add > 0) push(pos); if (tree[pos].l == l && tree[pos].r == r) { tree[pos].add = tag; tree[pos].colors = tag; return ; } else { if (l <= min(r, tree[pos + pos].r)) modify(pos + pos, l, min(r, tree[pos + pos].r), tag); if (max(l, tree[pos + pos + 1].l) <= r) modify(pos + pos + 1, max(l, tree[pos + pos + 1].l), r, tag); if (tree[pos + pos].add) push(pos + pos); if (tree[pos + pos + 1].add) push(pos + pos + 1); tree[pos].colors = tree[pos + pos].colors | tree[pos + pos + 1].colors; } } long long query (int pos, int l, int r) { if (tree[pos].add > 0) push(pos); if (tree[pos].l == l && tree[pos].r == r) { return tree[pos].colors; } long long answer = 0; if (l <= min(r, tree[pos + pos].r)) answer |= query(pos + pos, l, min(r, tree[pos + pos].r)); if (max(l, tree[pos + pos + 1].l) <= r) answer |= query(pos + pos + 1, max(l, tree[pos + pos + 1].l), r); return answer; } void color (int currentNode, int radius, int previousNode = 0, int carry = 0) { // cerr << "temp " << currentNode << endl; if (radius < carry) { return ; } if (previousNode != 0) { // cerr << "colored " << currentNode << " " << currentNode << " " << carry << endl; modify(1, currentNode, currentNode, (1LL << (long long)carry)); } else { modify(1, currentNode, currentNode, 0); } if (radius >= carry && currentNode > 1 && previousNode != currentNode / 2) { // cerr << "goes to " << currentNode / 2 << endl; if (radius >= carry + 1) color(currentNode / 2, radius, currentNode, carry + 1); } if (previousNode < currentNode || previousNode == 0) { // cerr << "stand at " << currentNode << endl; int l = currentNode; int r = currentNode; for(int i = carry; i <= radius; i++) { if (i == 0) modify(1, l, r, 0); else { if (l <= treeSize) { modify(1, l, min(r, treeSize), (1LL << (long long)(i))); // cerr << "colored " << l << " " << r << " " << i << endl; } else break; } l = l * 2; r = r * 2 + 1; } // cerr << tree[1].colors << endl; } else if (previousNode > currentNode) { if (2 * currentNode <= treeSize && 2 * currentNode != previousNode) { color(2 * currentNode, radius, currentNode, carry + 1); } if (2 * currentNode + 1 <= treeSize && 2 * currentNode + 1 != previousNode) { color(2 * currentNode + 1, radius, currentNode, carry + 1); } } } int LCA (int x, int y) { if (x == y) return x; if (x > y) return LCA(x / 2, y); else return LCA(x, y / 2); } long long lift (int from, int to) { // cerr << query(1, from, from) << endl; if (from == to) return query(1, from, to); else return (query(1, from, from) | lift(from / 2, to)); } int countOnes (long long t) { // cerr << "co: " << t << endl; int ret = 0; while (t > 0) { ++ret; t &= (t - 1); } return ret; } int findColorsOnPath (int x, int y) { // cerr << "---" << endl; int anc = LCA(x, y); return countOnes(lift(x, anc) | lift(y, anc)); } int findColorsInSubtree (int x) { int l = x, r = x; long long ret = 0; while (l <= treeSize) { ret |= query(1, l, min(r, treeSize)); l = l * 2; r = r * 2 + 1; } return countOnes(ret); } void solve (std::istream& inputStream, std::ostream& outputStream) { inputStream >> treeSize >> queriesNumber; init(1, 1, treeSize); for(size_t i = 0; i < queriesNumber; ++i) { // cerr << "-------" << endl; int queryType; inputStream >> queryType; if (queryType == 1) { int startNode; int radius; inputStream >> startNode >> radius; color(startNode, radius); } else if (queryType == 2) { int startNode; int finishNode; inputStream >> startNode >> finishNode; outputStream << findColorsOnPath(startNode, finishNode) << std::endl; } else if (queryType == 3) { int rootNode; inputStream >> rootNode; outputStream << findColorsInSubtree(rootNode) << std::endl; } } } int main(int argc, const char * argv[]) { // freopen("input.txt", "r", stdin); solve(cin, cout); return 0; }