Bzoj2038 小Z的袜子(hose)
Time Limit: 20000MS | Memory Limit: 265216KB | 64bit IO Format: %lld & %llu |
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。
Hint
Source
2009国家集训队
莫队算法。将询问按左端点所在区间分块,每块内按右端点大小排序,每次动态调整所求答案区间……
具体的概率按组合数算就行
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #define LL long long 8 using namespace std; 9 const int mxn=100000; 10 struct answer{ 11 LL a,b;//分数 12 int l,r;//端点 13 int q;//分块 14 int id; 15 }a[mxn]; 16 int cmpqr(const answer x,const answer y){ 17 if(x.q!=y.q) return x.q<y.q; 18 return x.r<y.r; 19 } 20 int cmpid(const answer x,const answer y){ 21 return x.id<y.id; 22 } 23 // 24 int c[mxn];//颜色 25 int n,m; 26 LL s[mxn]; 27 LL sqr(LL a){ 28 return a*a; 29 } 30 LL gcd(LL a,LL b){ 31 if(!b)return a; 32 return gcd(b,a%b); 33 } 34 void solve(){ 35 LL ans=0;int i; 36 int l=1,r=0; 37 for(i=1;i<=m;i++){ 38 while(l<a[i].l){ 39 ans-=sqr(s[c[l]]); 40 s[c[l]]--; 41 ans+=sqr(s[c[l]]); 42 l++; 43 } 44 while(l>a[i].l){ 45 l--; 46 ans-=sqr(s[c[l]]); 47 s[c[l]]++; 48 ans+=sqr(s[c[l]]); 49 50 } 51 while(r>a[i].r){ 52 ans-=sqr(s[c[r]]); 53 s[c[r]]--; 54 ans+=sqr(s[c[r]]); 55 r--; 56 } 57 while(r<a[i].r){ 58 r++; 59 ans-=sqr(s[c[r]]); 60 s[c[r]]++; 61 ans+=sqr(s[c[r]]); 62 63 } 64 a[i].a=ans-a[i].r+a[i].l-1; 65 a[i].b=(LL)(a[i].r-a[i].l)*(a[i].r-a[i].l+1);//总可能结果 66 LL tmp=gcd(a[i].a,a[i].b);//约分 67 a[i].a/=tmp; 68 a[i].b/=tmp; 69 } 70 return; 71 } 72 int main(){ 73 scanf("%d%d",&n,&m); 74 int size=sqrt(n); 75 int i,j; 76 for(i=1;i<=n;i++)scanf("%d",&c[i]); 77 for(i=1;i<=m;i++){ 78 scanf("%d%d",&a[i].l,&a[i].r); 79 a[i].id=i; 80 a[i].a=a[i].b=0; 81 a[i].q=(a[i].l-1)/size+1; 82 } 83 sort(a+1,a+m+1,cmpqr); 84 solve(); 85 sort(a+1,a+m+1,cmpid); 86 for(i=1;i<=m;i++){ 87 printf("%lld/%lld\n",a[i].a,a[i].b); 88 } 89 return 0; 90 }
本文为博主原创文章,转载请注明出处。