1. 程式人生 > 實用技巧 >LOJ#6499. 「雅禮集訓 2018 Day2」顏色 題解

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

題目連結

考慮分塊,設塊大小為\(S\)。每個塊用一個bitset記錄塊中顏色,整塊之間打st表,查詢的時候整塊st表查,零散部分暴力即可。

時間複雜度\(\Theta(\frac{nS\log S}{w}) - \Theta(\frac{n}{w}+S)\)

空間複雜度\(\Theta(n+\frac{nS\log S}{w})\)

code :

#include <bits/stdc++.h>
#define LL unsigned long long
using namespace std;
template <typename T> void read(T &x){
	static char ch; x = 0,ch = getchar();
	while (!isdigit(ch)) ch = getchar();
	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
const int N = 100005,L = 80;
struct Bitst{
	LL B[1563];
	inline void ins(int p){ B[p>>6] |= 1ull << (p&63); }
	inline void Or(Bitst &A){
		register int i = 0;
		for (; i < 1563; i += 16){
			B[i] |= A.B[i],
			B[i+1] |= A.B[i+1],
			B[i+2] |= A.B[i+2],
			B[i+3] |= A.B[i+3],
			B[i+4] |= A.B[i+4],
			B[i+5] |= A.B[i+5],
			B[i+6] |= A.B[i+6],
			B[i+7] |= A.B[i+7],
			B[i+8] |= A.B[i+8],
			B[i+9] |= A.B[i+9],
			B[i+10] |= A.B[i+10],
			B[i+11] |= A.B[i+11],
			B[i+12] |= A.B[i+12],
			B[i+13] |= A.B[i+13],
			B[i+14] |= A.B[i+14],
			B[i+15] |= A.B[i+15];
		}
		for (; i < 1563; ++i) B[i] |= A.B[i];
	}
}st[L+1][7],now;
int Log[L+50];
inline void work(int l,int r){
	if (l == r){ now.Or(st[l][0]); return; }
	static int t; t = Log[r-l+1];
	if (r-l+1 == (1<<t+1) && t+1<7){ now.Or(st[l][t+1]); return; }
	now.Or(st[l][t]),now.Or(st[r-(1<<t)+1][t]);
}
int n,a[N],siz;
inline int Cur(int i){ return (i-1)/siz+1; }
inline int Left(int c){ return (c-1)*siz+1; }
inline int Right(int c){ return min(n,c*siz); } 
int S[1<<16];
inline void initS(){
	for (int i = 0; i < 1<<16; ++i) S[i] = S[i>>1] + (i&1);
}
inline int Count(LL x){
	static int ret; ret = 0;
	while (x) ret += S[x&65535],x >>= 16;
	return ret;
}
int main(){
	register int i,j; int q,type;
	read(n),read(q),read(type);
	for (i = 1; i <= n; ++i) read(a[i]),--a[i];
	siz = max(1,n/L + (n%L?1:0));
	for (i = 1; i <= L && Left(i) <= n; ++i)
	for (j = Left(i); j <= Right(i); ++j) st[i][0].ins(a[j]);
	for (i = 1; i <= L+10; ++i){ Log[i] = Log[i-1]; while ((1<<Log[i]+1) < i) ++Log[i]; }
	for (j = 1; j <= Log[L]; ++j)
	for (i = 1; i+(1<<j)-1 <= L; ++i){
		memcpy(st[i][j].B,st[i][j-1].B,12504); 
		st[i][j].Or(st[i+(1<<j-1)][j-1]);
	}
	int ans = 0,k,l,r,cl,cr,ll; bool First = 1;
	initS();
	while (q--){
		read(k),memset(now.B,0,12504);
		while (k--){
			read(l),read(r);
			if (!First && type){
				l ^= ans,r ^= ans,l = l % n + 1,r = r % n + 1; if (l > r) swap(l,r);
			}
			cl = Cur(l),cr = Cur(r);
			if (cl + 1 >= cr) for (i = l; i <= r; ++i) now.ins(a[i]);
			else{
				work(cl+1,cr-1);
				for (i = l,ll = Right(cl); i <= ll; ++i) now.ins(a[i]);
				for (i = r,ll = Left(cr); i >= ll; --i) now.ins(a[i]);
			}
		}
		ans = 0;
		for (i = 0; i < 1563; ++i) if (now.B[i]) ans += Count(now.B[i]);
		write(ans),putchar('\n');
		First = 0;
	}
	return 0;
}