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