网上大片的莫队算法题解,先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))
但是实际上似乎被莫队完败了,但是没关系,毕竟我们这是在线算法啊

 1 var f:array[0..230,0..230] of longint;
 2     g:array[0..50010,0..230] of longint;
 3     be,c,s:array[0..50010] of longint;
 4     size,p,t,i,n,m,x,y:longint;
 5 
 6 function gcd(a,b:longint):longint;
 7   begin
 8     if b=0 then exit(a)
 9     else exit(gcd(b,a mod b));
10   end;
11 
12 procedure prework;
13   var i,j:longint;
14   begin
15     for i:=1 to n do
16       inc(g[c[i],be[i]]);
17     for i:=1 to p do
18       for j:=2 to t do
19         inc(g[i,j],g[i,j-1]);
20     for i:=1 to t do
21     begin
22       for j:=(i-1)*size+1 to n do
23       begin
24         if j mod size=1 then f[i,be[j]]:=f[i,be[j]-1];
25         inc(f[i,be[j]],s[c[j]]);
26         inc(s[c[j]]);
27       end;
28       fillchar(s,sizeof(s),0);
29     end;
30   end;
31 
32 procedure clear(l,r:longint);
33   var i:longint;
34   begin
35     for i:=l to r do
36       s[c[i]]:=0;
37   end;
38 
39 procedure ask(x,y:longint);
40   var i,a,b,d:longint;
41   begin
42     b:=int64(y-x+1)*int64(y-x) div 2;
43     a:=0;
44     if be[x]=be[y] then
45     begin
46       for i:=x to y do
47       begin
48         a:=a+s[c[i]];
49         inc(s[c[i]]);
50       end;
51       clear(x,y);
52     end
53     else begin
54       a:=f[be[x]+1,be[y]-1];
55       for i:=x to be[x]*size do
56       begin
57         if s[c[i]]=0 then s[c[i]]:=g[c[i],be[y]-1]-g[c[i],be[x]];
58         a:=a+s[c[i]];
59         inc(s[c[i]]);
60       end;
61       for i:=(be[y]-1)*size+1 to y do
62       begin
63         if s[c[i]]=0 then s[c[i]]:=g[c[i],be[y]-1]-g[c[i],be[x]];
64         a:=a+s[c[i]];
65         inc(s[c[i]]);
66       end;
67       clear(x,be[x]*size);
68       clear((be[y]-1)*size+1,y);
69     end;
70     d:=gcd(a,b);
71     writeln(a div d,'/',b div d);
72   end;
73 
74 begin
75   readln(n,m);
76   size:=trunc(sqrt(n));
77   for i:=1 to n do
78   begin
79     read(c[i]);
80     if c[i]>p then p:=c[i];
81     be[i]:=(i-1) div size+1;
82   end;
83   t:=i div size;
84   if i mod size<>0 then inc(t);
85   prework;
86   for i:=1 to m do
87   begin
88     readln(x,y);
89     ask(x,y);
90   end;
91 end.
View Code

 

posted on 2015-02-06 10:56  acphile  阅读(243)  评论(0编辑  收藏  举报