zoukankan      html  css  js  c++  java
  • bzoj 2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2038

    【题意】

        给定一个有颜色的序列,回答若干个询问:区间内任选两个颜色相同的概率。

    【思路】

        设一个颜色在区间内的出现次数为cnt,则抽到这种颜色的概率为:

            (cnt-1)*cnt/2 = 1+2+…+cnt-1

        对于一个区间我们就可以使用一个cnt数组通过扫一遍得出答案。暴力的话,可以拿两个指针,每次移动指针,对数据进行插入与删除。

        莫队算法就是在此基础上有序化了数据。将序列每sqrt(n)分成一块,根据查询的左端点所在块编号和右端点为第一二关键字排序。相邻的区间的重叠部分不重复计算,而是采用移动指针的方法,并通过合适的数据结构维护区间内的数据,支持在原来答案的基础上添加或删除数据即区间移动。

        关于复杂度的分析:

    一、i与i+1在同一块内,r单调递增,所以r是O(n)的。由于有n^0.5块,所以这一部分时间复杂度是n^1.5。
    二、i与i+1跨越一块,r最多变化n,由于有n^0.5块,所以这一部分时间复杂度是n^1.5
    三、i与i+1在同一块内时变化不超过n^0.5,跨越一块也不会超过2*n^0.5,不妨看作是n^0.5。由于有n个数,所以时间复杂度是n^1.5
    于是就变成了O(n^1.5)了

                                              from...不详

    【代码】

     1 #include<set>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
    10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    11 using namespace std;
    12 
    13 typedef long long ll;
    14 const int N = 5e4+10;
    15 
    16 ll read() {
    17     char c=getchar();
    18     ll f=1,x=0;
    19     while(!isdigit(c)) {
    20         if(c=='-') f=-1; c=getchar();
    21     }
    22     while(isdigit(c))
    23         x=x*10+c-'0',c=getchar();
    24     return x*f;
    25 }
    26 
    27 struct Node 
    28 {
    29     int pos,l,r,id;
    30     bool operator < (const Node& rhs) const
    31     {
    32         return pos<rhs.pos||(pos==rhs.pos&&r<rhs.r);
    33     }
    34 }q[N];
    35 
    36 ll gcd(ll a,ll b)
    37 {
    38     return b==0? a:gcd(b,a%b);
    39 }
    40 
    41 int n,m,c[N],cnt[N];
    42 pair<int,int> ans[N];
    43 
    44 int main()
    45 {
    46     n=read(),m=read();
    47     FOR(i,1,n) c[i]=read();
    48     int B=sqrt(n);
    49     FOR(i,1,m)
    50     {
    51         q[i].l=read();
    52         q[i].r=read();
    53         q[i].pos=(q[i].l-1)/B+1; 
    54         q[i].id=i;
    55     }
    56     sort(q+1,q+m+1);
    57     int l=1,r=0; ll now=0;
    58     FOR(i,1,m)
    59     {
    60         while(l>q[i].l)
    61             now+=cnt[c[--l]]++;
    62         while(l<q[i].l)
    63             now-=--cnt[c[l++]];
    64         while(r<q[i].r)
    65             now+=cnt[c[++r]]++;
    66         while(r>q[i].r)
    67             now-=--cnt[c[r--]];
    68         ll sum=(ll)(r-l+1)*(r-l)/2;
    69         ll g=gcd(sum,now);
    70         ans[q[i].id]=make_pair((int)now/g,(int)sum/g);
    71     }
    72     FOR(i,1,m)
    73         printf("%d/%d
    ",ans[i].first,ans[i].second);
    74     return 0;
    75 }
  • 相关阅读:
    30条MySQL优化总结
    安装了最新的pycharm不能自动补全的解决方法。路径中输入变成¥的解决方法
    You should consider upgrading via the 'python -m pip install --upgrade pip' command解决方法
    B站MySQL学习之笔记
    B站MySQL学习之job_grades表数据
    B站MySQL学习之student数据
    Faker 造相对真实的测试数据
    浏览器地址栏输入url后的过程
    cookie、session及token的区别
    Get和Post的区别
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5343725.html
Copyright © 2011-2022 走看看