BZOJ2506 : calc
在线做法:
若p不超过100,则可以先预处理,将所有满足a[x]%i=j的x从小到大放进链表q[i][j]中,查询时二分
预处理:O(100n)
查询:O(logn)
若p超过100,则满足条件的a[x]一定不超过100种
于是维护一个二维数组T,T[i][j]表示在前j个数里多有少个的权值是i
为了高速查询,可以将序列按每块100的大小分块,维护一个块状数组
查询时枚举所有可能的a[x],然后利用前缀和O(1)询问
预处理:O(100n)
查询:O(100)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include<cstdio> const int N=100001,K=10001,S=101,B=1001; int n,m,i,j,k,p,x,y,size=100,block,cnt,a[N],g[S],nxt[N],v[N],ed; int st[S][S],en[S][S],q[N*S]; int pos[N],idx[N],pool[N][S],b[K][B],tag[K][B]; inline void read( int &a){ char c; while (!(((c= getchar ())>= '0' )&&(c<= '9' )));a=c- '0' ; while (((c= getchar ())>= '0' )&&(c<= '9' ))(a*=10)+=c- '0' ;} inline void add( int x, int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} inline int vio( int p, int k, int l, int r){ int t=0; for (;k<K;k+=p)t+=tag[k][pos[r]-1]-tag[k][pos[l]-1]+pool[b[k][pos[r]]][idx[r]]-pool[b[k][pos[l]]][idx[l]]; return t; } inline int ask( int L, int R, int x){ int l=L,r=R,t=R+1,mid; while (l<=r) if (q[mid=(l+r)>>1]<=x)r=(t=mid)-1; else l=mid+1; return R-t+1; } int main(){ read(n),read(m); for (pos[0]=i=1;i<=n;i++){ read(a[i]); if (!b[a[i]][pos[i]=(i-1)/size+1])b[a[i]][pos[i]]=++cnt; pool[b[a[i]][pos[i]]][idx[i]=(i-1)%size+1]=1,tag[a[i]][pos[i]]++; } for (block=pos[n],i=1;i<=cnt;i++) for (j=2;j<=size;j++)pool[i][j]+=pool[i][j-1]; for (i=0;i<K;i++) for (j=2;j<=block;j++)tag[i][j]+=tag[i][j-1]; for (cnt=0,j=1;j<=size;j++){ for (ed=i=0;i<j;g[i++]=0); for (i=1;i<=n;i++)add(a[i]%j,i); for (i=0;i<j;en[j][i++]=cnt) for (st[j][i]=cnt+1,k=g[i];k;k=nxt[k])q[++cnt]=v[k]; } while (m--){ read(x),read(y),read(p),read(k),x--; printf ( "%d\n" ,p<=size?(ask(st[p][k],en[p][k],y)-ask(st[p][k],en[p][k],x)):vio(p,k,x,y)); } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步