Description
Input
Sample Input
5 2
1 5 2 3 7
1 3 2 1
2 5 3 0
Output
Sample Output
有很多询问,每一次询问询问一个区间内有多少个数被p除后余q
想了两分钟后想到了60%的前缀和做法,又想了一下,发现好像可以用莫队来做这道题
莫队的做法:先把输入存起来以l为关键字排一次序,然后用莫队的思想分块,每个块再以r为关键字从小到大排一次序,然后用一个桶来维护当前区间每一个数有多少个。最后暴力的计算答案,然而以为我没有打拍,有一个大于号打成小于号了,于是愉悦的爆零
把每一个询问拆分成1->l-1和1->r的形式,然后排一次序,那么就可以用扫描线做这道题了,我们存储两个桶,一个是g[i][j],表示被i除了之后余数是j的数有多少个(i<=100)另外一个是sum[i],表示当前数字i出现了多少次,对于一个询问,如果p小于100,那么直接在g数组中可以直接获得答案,如果p大于100,那么就在sum数组中把所有合法的情况加起来就可以了,这样做的时间复杂度是 10000−−−−−√∗m∗2 的(其实我觉得莫队也可以这样做啊)
我的代码其实是有点水的,如果要卡是会被卡掉的
话说比我的莫队模板还要短哎!
var
a,c:array[0..100005]of longint;
q:array[0..100005,1..5]of longint;
sum,tot:array[0..100005]of longint;
i,j,k,l,m,n,x,y,maxx,p,ans:longint;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=q[(i+j) div 2,1];
repeat
while q[i,1]do inc(i);
while q[j,1]>mid do dec(j);
if i<=j then
begin
q[0]:=q[i];
q[i]:=q[j];
q[j]:=q[0];
inc(i);
dec(j);
end;
until i>j;
if iif lq[(i+j) div 2,2];
repeat
while q[i,2]do inc(i);
while q[j,2]>mid do dec(j);
if i<=j then
begin
q[0]:=q[i];
q[i]:=q[j];
q[j]:=q[0];
inc(i);
dec(j);
end;
until i>j;
if iif lx,y:longint);
var
i:longint;
begin
for i:=x to y-1 do dec(sum[a[i]]);
end;
procedure work2(x,y:longint);
var
i:longint;
begin
for i:=x downto y+1 do dec(sum[a[i]]);
end;
procedure work3(x,y:longint);
var
i:longint;
begin
for i:=x+1 to y do inc(sum[a[i]]);
end;
procedure work4(x,y:longint);
var
i:longint;
begin
for i:=x-1 downto y do inc(sum[a[i]]);
end;
procedure init;
begin
readln(n,m);
for i:=1 to n do
begin
read(a[i]);
if a[i]>p then p:=a[i];
end;
readln;
for i:=1 to m do
begin
readln(q[i,1],q[i,2],q[i,3],q[i,4]);
q[i,5]:=i;
end;
qsort(1,m);
maxx:=trunc(sqrt(q[m,1]));
c[0]:=1;
c[1]:=1;
x:=0;
for i:=1 to m do
begin
if x<q[i,1] then
begin
inc(c[0]);
c[c[0]]:=i;
end;
while x<q[i,1] do x:=x+maxx;
end;
for i:=1 to c[0]-1 do qsort1(c[i],c[i+1]-1);
x:=1;
y:=1;
sum[a[1]]:=1;
end;
begin
//assign(input,'3.in'); reset(input);
init;
for i:=1 to m do
begin
ans:=0;
if x<q[i,1] then work1(x,q[i,1]) else work4(x,q[i,1]);
if y>q[i,2] then work2(y,q[i,2]) else work3(y,q[i,2]);
while q[i,4]<=p do
begin
ans:=ans+sum[q[i,4]];
q[i,4]:=q[i,4]+q[i,3];
end;
tot[q[i,5]]:=ans;
x:=q[i,1];
y:=q[i,2];
end;
for i:=1 to m do writeln(tot[i]);
// close(input);
end.