1. 程式人生 > 其它 >LOJ #6499. 「雅禮集訓 2018 Day2」顏色

LOJ #6499. 「雅禮集訓 2018 Day2」顏色

突然想起來這個題,作為總結寫個題解。

考慮這個問題比區間數顏色強很多,那麼要不然就離線,要不然線上考慮非 polylog 的做法。

顏色數資訊比較難合併,考慮用 bitset 來記錄顏色,合併就是 bitset 的按位或。

線上做法:四毛子,分成 \(w\) 個塊以及它們的顏色 bitset,然後用 ST 表預處理出塊的區間 bitset。詢問的時候整塊直接查 ST 表,散塊暴力掃,時間複雜度 \(\mathcal{O}(\frac{nm}{w})\)

離線做法:用莫隊把詢問的區間的 bitset 掃出來,最後再合併,時間複雜度 \(\mathcal{O}(n\sqrt m+\frac{nm}{w})=\mathcal{O}(\frac{nm}{w})\)

注意空間問題,由於卡空間後者應該過不了。

線上做法:

#include<iostream>
#include<cstdio>
#include<bitset>
#include<cmath>
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T>
T &read(T &r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 100001;
const int w = 64;
int n, m, p, a[N], _lg[N], lst;
int blo, bl[N];
std::bitset<100001>st[7][w+1], now;
void calc(int l, int r) {
	for(int i = l; i <= r; ++i) now[a[i]] = 1;
}
int main() {
	read(n); read(m); read(p);
	blo = std::ceil(1.0 * n / w);
	for(int i = 1; i <= n; ++i) {
		read(a[i]);
		_lg[i] = _lg[i-1] + ((1 << _lg[i-1]) == i ? 1 : 0);
		bl[i] = (i - 1) / blo + 1;
		st[0][bl[i]][a[i]] = 1;
	}
	for(int i = 1; i <= n; ++i) --_lg[i];
	for(int i = 1; i <= 6; ++i)
		for(int j = 1; j <= w && j + (1 << i) - 1 <= w; ++j)
			st[i][j] = st[i-1][j] | st[i-1][j+(1<<(i-1))];
	for(int i = 1, k, l, r; i <= m; ++i) {
		now.reset();
		read(k);
		for(int j = 1; j <= k; ++j) {
			read(l); read(r);
			if(p && i != 1) l = (l ^ lst) % n + 1, r = (r ^ lst) % n + 1;
			if(l > r) std::swap(l, r);
			if(bl[l] == bl[r]) calc(l, r);
			else {
				int cl = bl[l], cr = bl[r];
				if(l != bl[l] * blo - blo + 1) calc(l, bl[l] * blo), ++cl;
				if(r != bl[r] * blo) calc(bl[r] * blo - blo + 1, r), --cr;
				if(cl > cr) continue;
				int t = _lg[cr - cl + 1];
				now |= st[t][cl] | st[t][cr-(1<<t)+1];
			}
		}
		lst = now.count();
		printf("%d\n", lst);
	}
	return 0;
}