LibreOJ 6499. 「雅礼集训 2018 Day2」颜色【分块+bitset+ST表+卡常】
6499. 「雅礼集训 2018 Day2」颜色
【题目描述】
【题解】
分块+bitset+ST表+卡常
对于序列分块,每块用bitset存起来,然后用ST表预处理bitset的合并,然后就是一道卡常题了。
代码如下
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=100005,MAXQ=55,MAXP=10000/3+1,MOD=(1<<16)-1;
int n,m,P,K,Siz,RSiz,Ans,a[MAXN],block[MAXN],hsh[MAXN],Num[MOD+5],LOG[MAXQ];
#include<cctype>
char nc(){
static char buf[100000],*L=buf,*R=buf;
return (L==R&&(R=(L=buf)+fread(buf,1,100000,stdin),L==R))?EOF:*L++;
}
int read(){
int ret=0;char ch=nc();bool f=1;
for(;!isdigit(ch);ch=nc()) f^=!(ch^'-');
for(; isdigit(ch);ch=nc()) ret=ret*10+ch-48;
return f?ret:-ret;
}
struct BITSET{
unsigned int a[MAXP+5];
BITSET operator |(const BITSET b)const{
BITSET c;
for(int i=0;i<=K;++i) c.a[i]=a[i]|b.a[i];
return c;
}
void set(int x){a[x>>5]|=1u<<(x&31);}
void reset(){for(int i=0;i<=K;++i) a[i]=0;}
int count(){
int Now=0;
for(int i=0;i<=K;++i) Now+=Num[a[i]&MOD],Now+=Num[a[i]>>16];
return Now;
}
}f[MAXQ][7],s;
int main(){
n=read(),m=read(),P=read();
for(int i=0;i<65536;i++){
Num[i]=0;
for(int x=i;x;x-=x&-x) ++Num[i];
}
for(int i=2;i<MAXQ;i++) LOG[i]=LOG[i>>1]+1;
for(int i=1;i<=n;++i) hsh[i]=a[i]=read();
sort(hsh+1,hsh+1+n);K=unique(hsh+1,hsh+1+n)-hsh-1;
for(int i=1;i<=n;++i) a[i]=lower_bound(hsh+1,hsh+1+K,a[i])-hsh-1;
Siz=2000;K>>=5;
for(int i=1;i<=n;++i){
block[i]=block[i-1];
if(i%Siz==0) ++block[i],++RSiz;
f[block[i]][0].set(a[i]);
}
for(int j=1;j<=LOG[RSiz];++j)
for(int i=1;i<=RSiz-(1<<j)+1;++i) f[i][j]=f[i][j-1]|f[i+(1<<j-1)][j-1];
for(int j=0;j<m;++j){
int K=read();s.reset();
while(K--){
int L=read(),R=read();
if(P&&j) L=(L^Ans)%n+1,R=(R^Ans)%n+1;
if(L>R) swap(L,R);
if(block[L]==block[R]) for(int i=L;i<=R;++i) s.set(a[i]);
else{
if(block[L]==block[L-1]){
int i;
for(i=L;block[i]==block[L];++i) s.set(a[i]);
L=i;
}
if(block[R]==block[R+1]){
int i;
for(i=R;block[i]==block[R];--i) s.set(a[i]);
R=i;
}
if(block[L]<=block[R]){
int k=LOG[block[R]-block[L]+1];
s=s|f[block[L]][k]|f[block[R]-(1<<k)+1][k];
}
}
}
printf("%d\n",Ans=s.count());
}
return 0;
}