题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038
分析:
莫队模板题
用分块思想,将询问按开头大小分成sqrt(n)块,然后块内按询问结束排序。
然后暴力从(l,r)转移到(l,r+1)或(l,r-1)或(l-1,r)或(l+1,r)时间为O(1)
时间复杂度分析:
①若转移出现在块内,则块内所有询问之间的转移一共最多需要O(n),一共有n块,所以块内转移时间复杂度一共是O(nlogn)
②若转移出现在块和块之间,则一次块和块之间的转移最多需要O(n),一共有n次这种转移,所以块于块之间的转移时间复杂度一共是O(nlogn)
总时间复杂度为:O(2nlogn)≈O(nlogn)
代码:
type
node=record
l,r,id,pos:longint;
end;
var
c,cnt:array [1..60001] of int64;
a:array [1..60001] of node;
i,j:longint;
ans,m,n,l,r,k,block,h:int64;
procedure pai1(l,r:longint);
var
i,j,mid1,mid2:longint;
t:node;
begin
i:=l;
j:=r;
mid1:=a[(l+r) div 2].pos;
mid2:=a[(l+r) div 2].r;
repeat
while (a[i].pos<mid1) or ((a[i].pos=mid1) and (a[i].r<mid2)) do inc(i);
while (a[j].pos>mid1) or ((a[j].pos=mid1) and (a[j].r>mid2)) do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then pai1(l,j);
if i<r then pai1(i,r);
end;
procedure pai2(l,r:longint);
var
i,j,mid:longint;
t:node;
begin
i:=l;
j:=r;
mid:=a[(l+r) div 2].id;
repeat
while a[i].id<mid do inc(i);
while a[j].id>mid do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then pai2(l,j);
if i<r then pai2(i,r);
end;
procedure suan(x,k:longint);
begin
if k=1 then
ans:=ans+cnt[c[x]]*(cnt[c[x]]-1) else
ans:=ans-cnt[c[x]]*(cnt[c[x]]-1);
end;
function gcd(x,y:int64):int64;
begin
if x mod y=0 then
exit(y) else
exit(gcd(y,x mod y));
end;
begin
assign(input,'sock.in');
assign(output,'sock.out');
reset(input);
rewrite(output);
readln(n,m);
for i:=1 to n do
read(c[i]);
readln;
block:=trunc(sqrt(n));
for i:=1 to m do
begin
a[i].id:=i;
readln(a[i].l,a[i].r);
a[i].pos:=(a[i].l-1) div block+1;
end;
pai1(1,m);
l:=1;
r:=0;
for i:=1 to m do
begin
if a[i].l=a[i].r then
begin
a[i].l:=0;
a[i].r:=1;
continue;
end;
while r<a[i].r do
begin
inc(r);
suan(r,2);
inc(cnt[c[r]]);
suan(r,1);
end;
while r>a[i].r do
begin
suan(r,2);
dec(cnt[c[r]]);
suan(r,1);
dec(r);
end;
while l<a[i].l do
begin
suan(l,2);
dec(cnt[c[l]]);
suan(l,1);
inc(l);
end;
while l>a[i].l do
begin
dec(l);
suan(l,2);
inc(cnt[c[l]]);
suan(l,1);
end;
h:=(a[i].r-a[i].l+1);
h:=h*(a[i].r-a[i].l);
k:=gcd(ans,h);
a[i].r:=h div k;
a[i].l:=ans div k;
end;
pai2(1,m);
for i:=1 to m do
writeln(a[i].l,'/',a[i].r);
close(input);
close(output);
end.
数据:http://download.csdn.net/detail/boyxiejunboy/9423250