• BZOJ 2038 小Z的袜子(hose) 莫队算法模板题


    题目链接:

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

    题目大意:

    作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……
    具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。
    你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。

    思路:

    用莫队先分块,然后直接维护区间内数字出现次数平方和即可。

     1 #include<bits/stdc++.h>
     2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
     3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
     4 #define Min(a, b) ((a) < (b) ? (a) : (b))
     5 #define Mem(a) memset(a, 0, sizeof(a))
     6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
     7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
     8 #define lson ((o)<<1)
     9 #define rson ((o)<<1|1)
    10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
    11 using namespace std;
    12 inline int read()
    13 {
    14     int x=0,f=1;char ch=getchar();
    15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    17     return x*f;
    18 }
    19  
    20 typedef long long ll;
    21 const int maxn = 1000000 + 10;
    22 const int MOD = 1000000007;//const引用更快,宏定义也更快
    23 const ll INF = 1e16;
    24 const double eps = 1e-6;
    25  
    26 int a[maxn];
    27 int pos[maxn];//存储每一位分块编号
    28 struct query
    29 {
    30     int l, r, id;
    31     query(){}
    32     query(int l, int r, int id):l(l), r(r), id(id){}
    33     bool operator <(const query& a)const
    34     {
    35         if(pos[l] == pos[a.l])return r < a.r;//在同一分块内 莫队算法核心
    36         return l < a.l;
    37     }
    38 }b[maxn];
    39 ll num[maxn];//num[i]表示当前数字i出现的次数
    40 ll ans;//ans的含义如下:维护当前区间内数字出现次数平方和
    41 //分子 = For i = 1...n  num[i]*(num[i] - 1) / 2
    42 //分母 = (R - L + 1) * (R - L) / 2
    43 //转化一下得:
    44 //分子 = (For i = 1...n num[i]^2) - (For i = 1..n num[i]) = ans - (R - L + 1)
    45 //分母 = (R - L + 1) * (R - L)
    46 void update(int p, int add)//下标为p的数字加入或者删去 add为1表示加入 为-1表示删去
    47 {
    48     ans -= num[a[p]] * num[a[p]];//先把下标p的数字贡献删去
    49     num[a[p]] += add;//调整下标p数字出现次数
    50     ans += num[a[p]] * num[a[p]];//加上下标p数字贡献
    51 }
    52 struct node
    53 {
    54     ll a, b;
    55     node(){}
    56     node(ll a, ll b):a(a), b(b){}
    57 }Ans[maxn];
    58 int main()
    59 {
    60     int n, m;
    61     scanf("%d%d", &n, &m);
    62     for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    63     int len = (int)sqrt(n);
    64     for(int i = 1; i <= n; i++)pos[i] = i / len + 1;
    65     for(int i = 1; i <= m; i++)scanf("%d %d", &b[i].l, &b[i].r), b[i].id = i;
    66     sort(b + 1, b + 1 + m);
    67     int l = 1, r = 0;
    68     ll tmpa, tmpb;
    69     for(int i = 1; i <= m; i++)
    70     {
    71         for(; r < b[i].r; r++)update(r + 1, 1);
    72         for(; r > b[i].r; r--)update(r, -1);
    73         for(; l < b[i].l; l++)update(l, -1);
    74         for(; l > b[i].l; l--)update(l - 1, 1);//莫队写法
    75         tmpa = ans - (b[i].r - b[i].l + 1);
    76         tmpb = (ll)(b[i].r - b[i].l + 1) * (b[i].r - b[i].l);
    77         ll g = __gcd(tmpa, tmpb);
    78         tmpa /= g, tmpb /= g;
    79         Ans[b[i].id] = node(tmpa, tmpb);
    80     }
    81     for(int i = 1; i <= m; i++)printf("%lld/%lld
    ", Ans[i].a, Ans[i].b);
    82     return 0;
    83 }
    84 
  • 相关阅读:
    安装oh-my-zsh失败,可按以下方式安装
    aria2 for mac
    java抛出异常后,后续代码是否可继续执行
    mac多线程下载神器
    Oracle--大数据迁移--sqlldr技术的应用
    Windows版 GCC编译器安装和使用--MinGW
    Visual Studio 2015 安装与注册
    android studio 3.6 环境搭建(安装步骤)
    IDEA--主题样式设置
    数据--innercode--的处理
  • 原文地址:https://www.cnblogs.com/fzl194/p/9671459.html
Copyright © 2020-2023  润新知