P1494 小Z的袜子 普通莫队

Posted yuanweidao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1494 小Z的袜子 普通莫队相关的知识,希望对你有一定的参考价值。

我的第二道莫队题,对莫队又有了自己的看法。

在第一题的基础上之上,觉得莫队有个很关键的地方在于 莫队所维护的值是什么,怎么推出维护的公式来。

这道题就是这样,一开始还没自己推出公式来,也有几个坑点。

题目链接:https://www.luogu.org/problemnew/show/P1494

 

题目大意:给出区间值,询问给定的【l, r】区间内抽到两只颜色一样的概率是多少。

思路:

1.首先很重要的推出公式来,设颜色相同的数量分别为a, b, c...那么对于给定的区间【l, r】,概率为 (a * (a  - 1) / 2+ b * (b - 1) / 2 + c * (c - 1) / 2 + ...) / ((r - l + 1) * (r - l) / 2),化简为 (a ^ 2 + b ^ 2 + c ^2 + ... - (r - l + 1)) / ((r - l + 1) * (r - l)),因此cnt维护区间内的值的数量,再推出如何维护平方和的值就行了。

2.计算的数据会爆int,需要用long long ,并且计算的式子要 * 1ll 来转化成long long型,才不会WA。

3.区间 l == r, 分子分母小于等于0时,直接记录 0 / 1

代码如下:

技术图片
  1 #include<stdio.h>
  2 #include<math.h>
  3 #include<algorithm>
  4 using namespace std;
  5 const int MAXN = 50010;
  6 
  7 int arr[MAXN];
  8 int cnt[MAXN]; //区间内出现次数
  9 
 10 struct Qurey
 11 
 12     int l, r, id;
 13     int pos; //所属的块 
 14 q[MAXN];
 15 
 16 struct ANS
 17 
 18     long long fz, fm;
 19 ans[MAXN];
 20 
 21 bool cmp(Qurey a, Qurey b)
 22 
 23     if(a.pos == b.pos)
 24         return a.r < b.r;
 25     else
 26         return a.pos < b.pos;
 27 
 28 
 29 long long gcd(long long a, long long b)
 30 
 31     long long c;
 32     while(b)
 33     
 34         c = a % b;
 35         a = b;
 36         b = c;
 37     
 38     return a;
 39 
 40 
 41 int main()
 42 
 43     int n, m;
 44     scanf("%d%d", &n, &m);
 45     for(int i = 1; i <= n; i ++)
 46         scanf("%d", &arr[i]);
 47     int fk = sqrt(n);
 48     for(int i = 1; i <= m; i ++)
 49     
 50         scanf("%d%d", &q[i].l, &q[i].r);
 51         q[i].id = i;
 52         q[i].pos = (q[i].l - 1) / fk + 1;
 53     
 54     sort(q + 1, q + 1 + m, cmp);
 55     int left = 1, right = 0;
 56     long long sum = 0;
 57     for(int i = 1; i <= m; i ++)
 58     
 59         if(q[i].l == q[i].r)
 60         
 61             ans[q[i].id].fz = 0;
 62             ans[q[i].id].fm = 1;
 63             continue;
 64         
 65         while(left > q[i].l)
 66         
 67             left --;
 68             cnt[arr[left]] ++;
 69             sum += 2 *1ll* cnt[arr[left]] - 1;
 70         
 71         while(right < q[i].r)
 72         
 73             right ++;
 74             cnt[arr[right]] ++;
 75             sum += 2 *1ll* cnt[arr[right]] - 1;
 76         
 77         while(left < q[i].l)
 78         
 79             cnt[arr[left]] --;
 80             sum -= 2 *1ll* cnt[arr[left]] + 1;
 81             left ++;
 82         
 83         while(right > q[i].r)
 84         
 85             cnt[arr[right]] --;
 86             sum -= 2 *1ll* cnt[arr[right]] + 1;
 87             right --;
 88         
 89         long long fz = sum - (right - left + 1);
 90         long long fm = 1ll*(right - left + 1) * (right - left);
 91         if(fz <= 0 || fm <= 0)
 92         
 93             ans[q[i].id].fz = 0;
 94             ans[q[i].id].fm = 1;
 95             continue;
 96         
 97         long long temp = gcd(fz, fm);
 98         fz /= temp, fm /= temp;
 99         ans[q[i].id].fz = fz, ans[q[i].id].fm = fm;
100     
101     for(int i = 1; i <= m; i ++)
102     
103         printf("%lld/%lld\n", ans[i].fz, ans[i].fm);
104     
105     return 0;
106 
View Code

 

以上是关于P1494 小Z的袜子 普通莫队的主要内容,如果未能解决你的问题,请参考以下文章

P1494 [国家集训队]小Z的袜子(莫队算法)

P1494 [国家集训队]小Z的袜子(莫队)

P1494 [国家集训队]小Z的袜子 莫队模板

[洛谷P1494]小Z的袜子

Luogu P1494 [国家集训队]小Z的袜子

P1494 [国家集训队]小Z的袜子