"LibreOJ NOI Round # 1" North outside the school memories (looking nature + + doubling tree line)

https://loj.ac/problem/510

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));
		}
	}
}

Guess you like

Origin www.cnblogs.com/coldchair/p/12669041.html