For \ (n <= 100000 \) a, \ (X \) to \ (x + low (x) \) connected edge to form within the forest, each time it is to modify a chain to the root, and a query point.
For \ (n \) great, we need to think about something deeper.
Consider why \ (k> 2 \) the Add cycle many times when.
For example \ (K =. 3 \) , a minimum start bit \ (= 1 \) , each \ (~ MOD ~ 2 * K \) , will 1,2,1,2 cycle reached \ (O (the n-) \) .
Consider k is an odd number, would have been in a cycle, \ (the X-\) to \ (x + low (x) \) form a forest is actually several pieces of chain, because there can be inserted into the other side there is (there 2 inverse).
When \ (k \) is not odd, not only may increase the plus forward to this one becomes 0, jump to a higher position, one point may have multiple incoming edges.
In fact, considering only the index containing 2 \ (> = k contained \) is a plurality of strands, which is equivalent to part 2 k useless.
And in the place, take a log up to 2 times the index contained on \ (> = k contains a \) , or to jump to the middle of the next layer.
So, from any point, go \ (log \) times will come on the chain.
The chain can dynamically segment tree maintenance prescription, the question is how to find the beginning of a chain?
Multiplication: Pretreatment \ (f [i] [j ] \) , said a is an i, enable high \ (- 2 ^ J \) , where jumps, each jump to.
Time complexity: \ (log ^ 2 \)
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
int calc(int x) {
int s = 0;
while(x % 2 == 0) x /= 2, s ++;
return s;
}
const int M = 19260817;
const int N = (2e5 + 5) * 31;
struct hash {
int fi[M];
int h[N]; int nt[N], c[N], tot;
int& operator[] (int n) {
int y = n % M;
for(int p = fi[y]; p; p = nt[p])
if(h[p] == n) return c[p];
nt[++ tot] = fi[y], h[tot] = n, fi[y] = tot;
return c[tot];
}
int find(int n) {
int y = n % M;
for(int p = fi[y]; p; p = nt[p])
if(h[p] == n) return c[p];
return 0;
}
} f, rt;
#define i0 t[i].l
#define i1 t[i].r
struct tree {
int l, r, x;
} t[N]; int tt;
int pl, pr, px;
void add(int &i, int x, int y) {
if(y < pl || x > pr) return;
if(!i) i = ++ tt;
t[i].x ^= px;
if(x == y) return;
int m = x + y >> 1;
add(i0, x, m); add(i1, m + 1, y);
}
void ft(int i, int x, int y) {
if(!i || y < pl || x > pr) return;
if(x >= pl && y <= pr) { px ^= t[i].x; return;}
int m = x + y >> 1;
ft(i0, x, m); ft(i1, m + 1, y);
}
int n, q, k, k2;
int op, x, y;
int w[32][200005], w0[200005];
void build() {
ff(i, 1, k) {
int t = calc(i);
if(t >= k2) {
w0[i] = t > k2 ? w0[i / 2] : i;
w[0][i * 2 % k] = w0[i];
}
}
fo(j, 1, 31) ff(i, 1, k)
w[j][i] = w[j - 1][w[j - 1][i]];
}
int low(int x) {
int s = 1;
while(x % k == 0) s *= k, x /= k;
return x % k * s;
}
int low2(int x) {
int s = 1;
while(x % k == 0) s *= k, x /= k;
return x % k;
}
int qv(int x) {
int s = 1;
while(x % k == 0) s *= k, x /= k;
return s;
}
void add(int x, int y) {
while(x <= n) {
if(calc(low2(x)) >= k2) break;
f[x] ^= y;
x += low(x);
}
if(x > n) return;
// pp("%d %d\n", x, y);
int l = low(x);
int v = qv(x);
int s = (x - l) / v / k;
int z = w0[l / v];
fd(i, 31, 0) if(s >> i & 1) z = w[i][z];
pl = pr = x; px = y;
add(rt[z * v], 1, n);
}
int sum(int x) {
int ans = 0;
for(; x; ) {
ans ^= f.find(x);
int l = low(x);
if(calc(low2(x)) >= k2) {
int v = qv(x);
int s = (x - l) / v / k;
int z = w0[l / v];
fd(i, 31, 0) if(s >> i & 1) z = w[i][z];
pl = 1, pr = x, px = 0;
ft(rt.find(z * v), 1, n);
ans ^= px;
}
x -= l;
}
return ans;
}
int main() {
scanf("%d %d %d", &n, &q, &k);
k2 = calc(k);
build();
fo(i, 1, q) {
scanf("%d %d", &op, &x);
if(op == 1) {
scanf("%d", &y);
add(x, y);
} else {
pp("%d\n", sum(x));
}
}
}