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

    题目链接:

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

    解题思路:

      刚开始做的是Whuoj Problem 1551 - E - Pairs,用hash离散化复杂度O(n*m),感觉会Tle,不死心就尝试了一下,果然华丽丽的T了。

      然后搜了一下,发现了莫队算法,感觉莫涛聚聚真是一个人才。啧啧啧啧~

      莫队算法是一个用数组就可以轻易实现的神奇数据结构,可以处理一类无修改的离线区间查询问题(PS:暂时还没有遇到莫队解决更新区间查询的问题)

      莫队算法可以在O(1),实现[l, r]到[l, r±1] / [l±1, r]的转移,然后我们就可以对所有查询分sqrt(n)块,把每个查询所在的块号当做第一关键字,右端点作为第二关键字升序排列。

      然后进行状态转移即可。

      时间复杂度O(n*sqrt(n)):当i与i+1在同一个块内,则L最多移动sqrt(n),R最多移动n,所以复杂度为O(n*sqrt(n)).

                  当i与i+1不在同一块内,则L最多移动2*sqrt(n),R最多移动n,复杂度为O(n*sqrt(n)).

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 const int maxn = 500010;
     8 typedef long long LL;
     9 struct node
    10 {
    11     LL r, l, index;
    12 }q[maxn];
    13 LL a[maxn], vis[maxn], ans[maxn][2];
    14 LL n, m, lb;
    15 bool cmp (node a, node b)
    16 {
    17     if (a.l/lb == b.l/lb)
    18         return a.r < b.r;
    19     return a.l < b.l;
    20 }
    21 LL gcd (LL a, LL b)
    22 {
    23     return b?gcd(b, a%b):a;
    24 }
    25 int main ()
    26 {
    27     while (scanf ("%lld %lld", &n, &m) != EOF)
    28     {
    29         for (int i=1; i<=n; i++)
    30             scanf ("%lld", &a[i]);
    31         for (int i=0; i<m; i++)
    32         {
    33             scanf ("%lld %lld", &q[i].l, &q[i].r);
    34             q[i].index = i;
    35         }
    36         lb = sqrt (1.0*n);
    37         sort (q, q+m, cmp);
    38         memset (vis, 0, sizeof(vis));
    39         LL res, l, r;
    40         res = 0;
    41         l = r = 1;
    42         vis[a[1]] ++;
    43         for (int i=0; i<m; i++)
    44         {
    45             while (r < q[i].r)
    46             {
    47                 r ++;//C(2,n+1) = C(2,n)+n
    48                 res += vis[a[r]];
    49                 vis[a[r]] ++;
    50             }
    51             while (r > q[i].r)
    52             {
    53                 vis[a[r]] --;
    54                 res -= vis[a[r]];
    55                 r --;
    56             }
    57             while (l < q[i].l)
    58             {
    59                 vis[a[l]] --;
    60                 res -= vis[a[l]];
    61                 l ++;
    62             }
    63             while (l > q[i].l)
    64             {
    65                 l --;
    66                 res += vis[a[l]];
    67                 vis[a[l]] ++;
    68             }
    69             LL mu = (q[i].r - q[i].l + 1)*(q[i].r - q[i].l)/2;
    70             if (!res)
    71             {
    72                 ans[q[i].index][0] = 0;
    73                 ans[q[i].index][1] = 1;
    74                 continue;
    75             }
    76             LL num = gcd (res, mu);
    77             ans[q[i].index][0] = res / num;
    78             ans[q[i].index][1] = mu / num;
    79         }
    80         for (int i=0; i<m; i++)
    81             printf ("%lld/%lld
    ", ans[i][0], ans[i][1]);
    82     }
    83     return 0;
    84 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    Linux 下如何查看一个组内的有哪些用户
    Linux下查看用户列表
    用pureftpd+pureDB虚拟用户,建立一个简单安全(不需要数据库支持)的linux ftp站
    pure-ftp中如何设置匿名帐号,自定义匿名帐号访问指定目录
    PUTTY中永久更改字体大小
    Pure-ftpd 如何配置多用户,且A用户具有上传下载权限,B用户只有下载权限?
    windows10访问ftp中文乱码怎么办?
    WPF DynamicDataDisplay.dll 下载
    C# windows presentation foundation 项目中不支持Application
    c# NDP472-KB4054530-x86-x64-AllOS-CHS下载
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4681157.html
Copyright © 2011-2022 走看看