zoukankan      html  css  js  c++  java
  • 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
    ", ans[i].fz, ans[i].fm);
    104     }
    105     return 0;
    106 }
    View Code
  • 相关阅读:
    最大流模板
    大数相加
    . Number throry
    掷骰子 dp
    Java常用类库2
    简单注册功能(未连接数据库)
    Java常用类库
    人机猜拳
    租车系统
    Java一些概念
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/10988957.html
Copyright © 2011-2022 走看看