离线+权值分块。无法在线,每个节点存不下100*100。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100500 #define maxm 10500 using namespace std; struct query { int pos,id,val,a,b; }q[maxn*3]; int n,m,cnt[maxm],a[maxn*3],ans[maxn*3],aa,b,c,d,f[150][150]; bool vis[maxn*3]; bool cmp(query x,query y) { if (x.pos==y.pos) return x.id<y.id; return x.pos<y.pos; } void insert(int x) { cnt[a[x]]++; for (int i=1;i<=100;i++) f[i][a[x]%i]++; } int main() { memset(f,0,sizeof(f)); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=m;i++) { scanf("%d%d%d%d",&aa,&b,&c,&d); q[2*i-1].pos=aa-1;q[2*i-1].id=i;q[2*i-1].val=-1;q[2*i-1].a=c;q[2*i-1].b=d; q[2*i].pos=b;q[2*i].id=i;q[2*i].val=1;q[2*i].a=c;q[2*i].b=d; } sort(q+1,q+2*m+1,cmp); int last=1; for (int i=1;i<=2*m;i++) { for (int j=last;j<=q[i].pos;j++) insert(j); last=q[i].pos+1; if (q[i].a>100) { int ret=0; for (int k=0;k*q[i].a+q[i].b<=10000;k++) ret+=cnt[k*q[i].a+q[i].b]; ans[q[i].id]+=q[i].val*ret; } else ans[q[i].id]+=q[i].val*f[q[i].a][q[i].b]; } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }