标签:image for sig blog using 分块 技术分享 its 部分
给你数组A和B,A B中的元素大小都不超过5w,且两两不同。
q次询问,每次给你个k,问你有多少对(i,j),满足A(i)%B(j)==k。
如题目所言模拟bitset的过程,实质上是个分块,每块的大小定为63。
一个小技巧是对于最终的那个数组w,分块后记63个w数组,每个数组最前面一块是零散的部分,大小从1~63,这样比较好操作。
最后把63个w里面的每一位的值都异或起来,就是对应的k的答案。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int SZ=63; typedef unsigned long long ull; ull blo[805],b[67][805],lss[67]; int T,n,m,q,sum=794,l[805],r[805],num[50005],sz[805]; bool a[50005],c[50005]; int main(){ int x; scanf("%d",&T); for(;T;--T){ memset(a,0,sizeof(a)); memset(blo,0,sizeof(blo)); memset(b,0,sizeof(b)); memset(lss,0,sizeof(lss)); memset(l,0,sizeof(l)); memset(r,0,sizeof(r)); memset(num,0,sizeof(num)); memset(sz,0,sizeof(sz)); memset(c,0,sizeof(c)); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;++i){ scanf("%d",&x); a[x]=1; } r[0]=-1; for(int i=1;i<=sum;++i){ l[i]=r[i-1]+1; r[i]=min(i*SZ-1,50000); sz[i]=r[i]-l[i]+1; for(int j=l[i],p=0;j<=r[i];++j,++p){ if(a[j]){ blo[i]|=((ull)1<<p); } num[j]=i; } } for(;m;--m){ scanf("%d",&x); for(int ql=0;ql<=50000;ql+=x){ int qr=min(ql+x-1,50000); if(num[ql]==num[qr]){ int fls=ql-l[num[ql]]; lss[qr-ql+1]^=((blo[num[ql]]>>fls)&(((ull)1<<(qr-ql+1))-(ull)1)); } else{ int ls=r[num[ql]]-ql+1; for(int i=num[ql]+1,j=1;i<num[qr];++i,++j){ b[ls][j]^=blo[i]; } int rs=qr-l[num[qr]]+1; lss[ls]^=(blo[num[ql]]>>(sz[num[ql]]-ls)); b[ls][num[qr]-num[ql]]^=(blo[num[qr]]&(((ull)1<<rs)-(ull)1)); } } } for(int i=1;i<=SZ;++i){ for(int j=0;j<i;++j){ c[j]^=((lss[i]>>j)&(ull)1); } int now=0,wei; for(int k=i,p=1;k<=50000;++k,++p,++wei){ if(p%SZ==1){ ++now; wei=0; } c[k]^=((b[i][now]>>wei)&((ull)1)); } } for(;q;--q){ scanf("%d",&x); printf("%d\n",c[x]); } } return 0; }
【分块】【bitset】hdu6085 Rikka with Candies
标签:image for sig blog using 分块 技术分享 its 部分
原文地址:http://www.cnblogs.com/autsky-jadek/p/7308919.html