bzoj2038

时间:2024-12-04 23:35:02

网上大片的莫队算法题解,先orz一下莫队
什么不会莫队?没事我来篇低端的
分块大法好啊,我们知道对于区间[l,r]答案是S/P P是一下子可以算出来的,S=∑(pj-1)*pj/2 pj表示区间内颜色为j的数目
先记录ans[i,j]表示第i块到第j块之间的S
然后再记录颜色g[i,j]表示到第i块颜色为j的数目
然后暴力统计不在整块内颜色对答案的贡献即可
20分钟就1A了,非常好写
虽然理论复杂度和莫队差不多O(nsqrt(n))
但是实际上似乎被莫队完败了,但是没关系,毕竟我们这是在线算法啊

 var f:array[..,..] of longint;
g:array[..,..] of longint;
be,c,s:array[..] of longint;
size,p,t,i,n,m,x,y:longint; function gcd(a,b:longint):longint;
begin
if b= then exit(a)
else exit(gcd(b,a mod b));
end; procedure prework;
var i,j:longint;
begin
for i:= to n do
inc(g[c[i],be[i]]);
for i:= to p do
for j:= to t do
inc(g[i,j],g[i,j-]);
for i:= to t do
begin
for j:=(i-)*size+ to n do
begin
if j mod size= then f[i,be[j]]:=f[i,be[j]-];
inc(f[i,be[j]],s[c[j]]);
inc(s[c[j]]);
end;
fillchar(s,sizeof(s),);
end;
end; procedure clear(l,r:longint);
var i:longint;
begin
for i:=l to r do
s[c[i]]:=;
end; procedure ask(x,y:longint);
var i,a,b,d:longint;
begin
b:=int64(y-x+)*int64(y-x) div ;
a:=;
if be[x]=be[y] then
begin
for i:=x to y do
begin
a:=a+s[c[i]];
inc(s[c[i]]);
end;
clear(x,y);
end
else begin
a:=f[be[x]+,be[y]-];
for i:=x to be[x]*size do
begin
if s[c[i]]= then s[c[i]]:=g[c[i],be[y]-]-g[c[i],be[x]];
a:=a+s[c[i]];
inc(s[c[i]]);
end;
for i:=(be[y]-)*size+ to y do
begin
if s[c[i]]= then s[c[i]]:=g[c[i],be[y]-]-g[c[i],be[x]];
a:=a+s[c[i]];
inc(s[c[i]]);
end;
clear(x,be[x]*size);
clear((be[y]-)*size+,y);
end;
d:=gcd(a,b);
writeln(a div d,'/',b div d);
end; begin
readln(n,m);
size:=trunc(sqrt(n));
for i:= to n do
begin
read(c[i]);
if c[i]>p then p:=c[i];
be[i]:=(i-) div size+;
end;
t:=i div size;
if i mod size<> then inc(t);
prework;
for i:= to m do
begin
readln(x,y);
ask(x,y);
end;
end.