BZOJ 2038 [2009国家集训队]小Z的袜子(hose)

 

2038: [2009国家集训队]小Z的袜子(hose)

Description

作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。 你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。

Input

输入文件第一行包含两个正整数N和M。N为袜子的数量,M为小Z所提的询问的数量。接下来一行包含N个正整数Ci,其中Ci表示第i只袜子的颜色,相同的颜色用相同的数字表示。再接下来M行,每行两个正整数L,R表示一个询问。

Output

包含M行,对于每个询问在一行中输出分数A/B表示从该询问的区间[L,R]中随机抽出两只袜子颜色相同的概率。若该概率为0则输出0/1,否则输出的A/B必须为最简分数。(详见样例)

Sample Input

6 4
1 2 3 3 3 2
2 6
1 3
3 5
1 6

Sample Output

2/5
0/1
1/1
4/15
【样例解释】
询问1:共C(5,2)=10种可能,其中抽出两个2有1种可能,抽出两个3有3种可能,概率为(1+3)/10=4/10=2/5。
询问2:共C(3,2)=3种可能,无法抽到颜色相同的袜子,概率为0/3=0/1。
询问3:共C(3,2)=3种可能,均为抽出两个3,概率为3/3=1/1。
注:上述C(a, b)表示组合数,组合数C(a, b)等价于在a个不同的物品中选取b个的选取方案数。 【数据规模和约定】
30%的数据中 N,M ≤ 5000;
60%的数据中 N,M ≤ 25000;
100%的数据中 N,M ≤ 50000,1 ≤ L < R ≤ N,Ci ≤ N。

Source

版权所有者:莫涛


  这是一道极为经典的题目。注意到一点,如果我们有计算完[L, R]时的“中间变量”(在本题为每个数出现的次数),那么[L - 1, R]、[L + 1, R]、[L, R - 1]、[L, R + 1]都能够在“中间变量”的“基本操作时间复杂度”(O(1)orO(log n)……)得出。

  例如在此题中,我们如果列出算式,可以轻易发现[L,R]对应的答案通过区间内各颜色数目的平方和快速计算,如果辅助存储区间内各颜色数目,那么O(1)的比邻状态转移就能够实现。

  以此便可介入此题。发现对于一个询问,可以从上一个询问开始通过移动区间得到现有答案。但是,这样很明显不优。状态间的转移即是左端点与右端点的位移,复杂度就是abs(L1 - L2) + abs(R1 - R2)。如果出题人足够邪恶,以至于一次转移是O(n)的,总的算下来O(nq)绝对无法接受。(但我做了实验并没有TLE)。

  当然,有人会说,这道题并没有强制在线,我们可以按照恰当的顺序去解决每个询问。例如,按照左端点从小到大排序,如果左端点相同再右端点从小到大排序。这样确实似乎可以,但出题人也可以乱卡,让右端点乱跳,一次转移同样可以做到O(n)。

  于是,就有人强推曼哈顿最小生成树(可以让顺序完美),但代码复杂度太高,同样也是O(nlogn)的复杂度。我们信息学竞赛不是“完美主义”,很有可能因小失大。

  于是“莫队”(因为比赛常常当队长)说,可以把左端点的排序“模糊处理”,允许在一定区间内的左端点其右端点单调递增。一定区间?这大概就是分块了。我们并不需要去专门维护这个块,只是在排序时用到。假设块长O(k),而一个块右端点最多跳O(n),有O(n/k)个块,故右端点最多跳O(n^2/k)次。左端点每次最多跳O(k)次,故左端点最多跳O(nk)次。

  我们发现,左右端点乱跳次数的乘积是相对一定的,为O(n^3),所以若k=sqrt(n),结果最优,复杂度是O(n*sqrt(n))的。

  但是,话说回来,这类题目为什么不能使用线段树一类的数据结构?理由很简单,颜色太多了。但据说有很强的方法,反正我不会。

  最后说一句,这道题要A特别简单。注:“莫队算法”=分块离线暴力

 

Type 直接按照顺序做 无脑排序 分块排序
Time 12228 ms 5680 ms

568 ms

 

  当然,可以只sort一次,能开int就开int。904 ms-〉812 ms-〉764 ms-〉568 ms

 

 1 /************************************************************** 
 2     Problem: 2038 
 3     User: Doggu 
 4     Language: C++ 
 5     Result: Accepted 
 6     Time:568 ms 
 7     Memory:2592 kb 
 8 ****************************************************************/
 9   
10 #include <cstdio> 
11 #include <algorithm> 
12 #include <cmath> 
13 using namespace std; 
14 template<class T>inline void readin(T &res) { 
15     static char ch;T flag=1; 
16     while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1; 
17     res=ch-48; 
18     while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48; 
19     res*=flag; 
20 } 
21 const int N = 50010; 
22 const int Q = 50010; 
23 int n, q, K, aa[N], num[N]; 
24 struct data{ 
25     int L, R, ord; 
26     bool operator< (const data &rhs) const {return L/K==rhs.L/K?R<rhs.R:L<rhs.L;} 
27 }que[Q]; 
28 long long x[N], y[N];inline long long gcd(long long a,long long b) {if(b==0) return a;return gcd(b,a%b);} 
29 int main() { 
30     readin(n);readin(q);K=floor(sqrt(n)); 
31     for( int i = 1; i <= n; i++ ) readin(aa[i]); 
32     for( int i = 1; i <= q; i++ ) readin(que[i].L),readin(que[i].R),que[i].ord=i; 
33     sort(que+1,que+q+1); 
34     int L = 1, R = 0, tot = 0; 
35     long long xs, ys, temp; 
36     for( int i = 1; i <= q; i++ ) { 
37         while(R<que[i].R) { 
38             R++; 
39             tot+=2*num[aa[R]]+1; 
40             num[aa[R]]++; 
41         } 
42         while(que[i].R<R) { 
43             num[aa[R]]--; 
44             tot-=2*num[aa[R]]+1; 
45             R--; 
46         } 
47         while(que[i].L<L) { 
48             L--; 
49             tot+=2*num[aa[L]]+1; 
50             num[aa[L]]++; 
51         } 
52         while(L<que[i].L) { 
53             num[aa[L]]--; 
54             tot-=2*num[aa[L]]+1; 
55             L++; 
56         } 
57         xs=tot-(R-L+1);ys=(long long)(R-L+1)*(R-L);temp=gcd(xs,ys); 
58         x[que[i].ord]=xs/temp;y[que[i].ord]=ys/temp; 
59     } 
60     //sort(que+1,que+q+1,cmp2); 
61     for( int i = 1;i <= q; i++ ) printf("%lld/%lld\n",x[i],y[i]); 
62     return 0; 
63 }
莫队

 

  

posted @ 2017-06-07 21:01 Doggu 阅读(...) 评论(...) 编辑 收藏