标签:
考虑离线,首先可以把每个询问的区间转化成[1,x]的形式
然后对询问的右端点排序
接着从左往右扫,记录每个数出现的次数,以及模数小于100的所有结果出现的次数
对于P小于100的询问,直接得到答案
对于P大于100的询问,暴力枚举得到答案
复杂度O(nsqrt(n))
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define N 233333
using namespace std;
inline int read(){
int ret=0;char ch=getchar();
while (ch<‘0‘||ch>‘9‘) ch=getchar();
while (‘0‘<=ch&&ch<=‘9‘){
ret=ret*10-48+ch;
ch=getchar();
}
return ret;
}
int a[N],n;
struct query{
int pos,P,mod,id;
query(){}
query(int _pos,int _P,int _mod,int _id):pos(_pos),P(_P),mod(_mod),id(_id){}
} q[N];
bool operator <(const query &x,const query &y){
return x.pos<y.pos;
}
int ans[N],cnt[23333],res[233][333];
int main(){
n=read();int Q=read(),m=0;
for (int i=1;i<=n;++i) a[i]=read();
for (int i=1;i<=Q;++i){
int x=read(),y=read(),z=read(),tmp=read();
q[++m]=query(x-1,z,tmp,-i);
q[++m]=query(y,z,tmp,i);
}
sort(q+1,q+m+1);
int j=1;
memset(cnt,0,sizeof(cnt));
memset(res,0,sizeof(res));
memset(ans,0,sizeof(ans));
for (int i=1;i<=m;++i){
for (;j<=q[i].pos;++j){
++cnt[a[j]];
for (int k=1;k<=100;++k) ++res[k][a[j]%k];
}
int now=0;
if (q[i].P>100)
for (int k=0;k*q[i].P+q[i].mod<=10000;++k)
now+=cnt[k*q[i].P+q[i].mod];
else now=res[q[i].P][q[i].mod];
ans[abs(q[i].id)]+=q[i].id/abs(q[i].id)*now;
}
for (int i=1;i<=Q;++i) printf("%d\n",ans[i]);
return 0;
}
标签:
原文地址:http://www.cnblogs.com/wangyurzee7/p/5179693.html