Description
Data Constraint
Solution
我们可以机智地把问题拆分成两个询问,以类似前缀和的求答案的方法,用1~r的ans减去1~l-1。用一条扫描线,把扫过的元素加入一个桶里,对于每个询问,枚举mod p余q的数,把桶里的值加入答案。因为当p太小时,这样的枚举效率很低,所以对于p我们可以分类计算。
1. 当
p≤maxa[i]−−−−−−√
时,直接开一个二维的数组,表示扫过的元素中mod i 余 j 的元素个数,询问时直接用。
2. 当
p>maxa[i]−−−−−−√
时,可以证明枚举的数的个数不会超过
maxa[i]−−−−−−√
,所以直接枚举计算。
因为当p<100时用第一种方法不会有影响,所以直接把界限设为100。
Code
var
s:array[0..100,0..100]of longint;
t:array[0..10000] of longint;
a,ans:array[1..100000] of longint;
w:array[0..200005,1..5] of longint;
n,m,x,y,p,q,i,j,z,maxn,sum:longint;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
i:=l;j:=r;
mid:=w[(l+r)div 2,1];
repeat
while w[i,1]<mid do inc(i);
while mid<w[j,1] do dec(j);
if i<=j then
begin
w[0]:=w[i];w[i]:=w[j];w[j]:=w[0];
inc(i);dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
begin
readln(n,m);
for i:=1 to n do read(a[i]);
for i:=1 to m do
begin
readln(x,y,p,q);
inc(sum);
w[sum,1]:=x-1;w[sum,2]:=p;w[sum,3]:=q;w[sum,4]:=i;w[sum,5]:=-1;
inc(sum);
w[sum,1]:=y;w[sum,2]:=p;w[sum,3]:=q;w[sum,4]:=i;w[sum,5]:=1;
end;
qsort(1,sum);
i:=0;
while i<2*m do
begin
inc(i);
while z<w[i,1] do
begin
inc(z);
inc(t[a[z]]);
maxn:=max(maxn,a[z]);
for j:=1 to 100 do inc(s[j,a[z] mod j]);
end;
if w[i,2]<=100 then
begin
ans[w[i,4]]:=ans[w[i,4]]+w[i,5]*s[w[i,2],w[i,3]];
continue;
end;
for j:=0 to max(0,(maxn-w[i,3])div w[i,2]) do
ans[w[i,4]]:=ans[w[i,4]]+w[i,5]*t[j*w[i,2]+w[i,3]];
end;
for i:=1 to m do writeln(ans[i]);
end.