P2639 [BZOJ] 矩阵计算
给定一个 \(n_1 \times n_2\) 的矩阵 , \(m\) 个询问 , 求一个矩阵中数出现次数的平方贡献和。
\(n1,n2 \leq 2 \times 10^2,m \leq 10^5\)。
可以用二维莫队 , 复杂度就是 \(O(n^2m^{\frac 3 4})\)。分块的话复杂度 \(O(n^{\frac 3 2}m)\) , 要快。
莫队的复杂度约为 : \(nm^{\frac{k-1}{k}}\) , \(k\) 为关键字个数。
对于 \(k\) 维的莫队 , 复杂度约为 : \(n^km^{\frac{2k-1}{2k}}\)。
这是底 , 除非压关键字。
但是细节比较多 , 各个关键字排列不同 , 所以很麻烦。
Uses math;
Const
question=100000+10;
total=200+10;
var
sqrnum,bucket:array[-1..sqr(total)] of longint;
matrix:array[-1..total,-1..total] of longint;
point:array[-1..7,-1..question] of longint;
ans:array[-1..question] of longint;
i,j,m,a,b,c,d,n1,n2,sum,node_num:longint;
procedure Swap(var a,b:longint); var t:longint; begin t:=a; a:=b; b:=t; end;
function Locate(node:longint):longint;
begin
if node mod node_num=0 then exit(node div node_num);
exit(node div node_num+1);
end;
procedure Sort(l,r:longint);
var i,j,k,s1,s2,s3,s4:longint;
begin
i:=l; j:=r; s1:=point[5,(l+r) >> 1]; s2:=point[2,(l+r) >> 1]; s3:=point[6,(l+r) >> 1]; s4:=point[4,(l+r) >> 1];
repeat
while (point[5,i]<s1)or((point[5,i]=s1)and(point[2,i]<s2))or((point[5,i]=s1)and(point[2,i]=s2)and(point[6,i]<s3))
or((point[5,i]=s1)and(point[2,i]=s2)and(point[6,i]=s3)and(point[4,i]<s4)) do inc(i);
while (point[5,j]>s1)or((point[5,j]=s1)and(point[2,j]>s2))or((point[5,j]=s1)and(point[2,j]=s2)and(point[6,j]>s3))
or((point[5,j]=s1)and(point[2,j]=s2)and(point[6,j]=s3)and(point[4,j]>s4)) do dec(j);
if i<=j then begin for k:=1 to 7 do Swap(point[k,i],point[k,j]); inc(i); dec(j); end;
until i>=j;
if i<r then Sort(i,r); if j>l then Sort(l,j);
end;
procedure Ready;
var i,j,k,e,f,g,h:longint;
begin
read(n1,n2); for i:=1 to n1 do for j:=1 to n2 do read(matrix[i,j]);
read(m); node_num:=trunc(sqrt(n1*n2)/sqrt(sqrt(m)));
for i:=1 to sqr(total) do sqrnum[i]:=sqr(i);
for i:=1 to m do
begin
point[7,i]:=i; read(e,f,g,h);
point[1,i]:=min(e,g); point[2,i]:=min(f,h); point[3,i]:=max(e,g); point[4,i]:=max(f,h);
point[5,i]:=Locate(point[1,i]); point[6,i]:=Locate(point[3,i]);
end;
Sort(1,m); a:=1; b:=1; c:=1; d:=1; sum:=1; bucket[matrix[1,1]]:=1;
end;
procedure Transefer(key,l,r,add,mode:longint);
var i:longint;
begin
if mode=1 then for i:=l to r do
begin dec(sum,sqrnum[bucket[matrix[key,i]]]); inc(bucket[matrix[key,i]],add);
inc(sum,sqrnum[bucket[matrix[key,i]]]); end;
if mode=2 then for i:=l to r do
begin dec(sum,sqrnum[bucket[matrix[i,key]]]); inc(bucket[matrix[i,key]],add);
inc(sum,sqrnum[bucket[matrix[i,key]]]); end;
end;
begin
Ready;
for i:=1 to m do
begin
while (a>point[1,i]) do begin dec(a); Transefer(a,b,d,1,1); end;
while (c>point[3,i]) do begin Transefer(c,b,d,-1,1); dec(c); end;
while (c<point[3,i]) do begin inc(c); Transefer(c,b,d,1,1); end;
while (a<point[1,i]) do begin Transefer(a,b,d,-1,1); inc(a); end;
while (b>point[2,i]) do begin dec(b); Transefer(b,a,c,1,2); end;
while (d>point[4,i]) do begin Transefer(d,a,c,-1,2); dec(d); end;
while (d<point[4,i]) do begin inc(d); Transefer(d,a,c,1,2); end;
while (b<point[2,i]) do begin Transefer(b,a,c,-1,2); inc(b); end;
ans[point[7,i]]:=sum;
end;
for i:=1 to m do writeln(ans[i]);
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿