HYSBZ 2038 小Z的袜子(hose) (莫队算法入门)

题意:取一段区间,求区间中任取两个数相同的概率;

思路:所求概率P=(A*(A-1)/2+B*(B-1)/2+......)/(R-L+1)*(R-L)/2化简得P=(A*A+B*B+......+Z*Z-(R-L+1))/(R-L+1)*(R-L);

将询问区间左端点放在同一分块中处理,每次处理一个块中的所有询问,对于同一块,询问右端点按严格递增处理,左端点不断移动;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int t,n,m,unit;
int a[500010],num[500010];
struct node
{
    int id,L,R;
}M[500010];
int cmp(node a,node b)
{
    if(a.L/unit!=b.L/unit) return a.L/unit<b.L/unit;
    return a.R<b.R;
}
long long gcd(long long a,long long b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
struct que
{
    long long a,b;
    void reduce() //分数约分
    {
        long long d=gcd(a,b);
        a/=d;b/=d;
    }
}ans[500010];
void work()
{
    int L=1,R=0;
    long long temp=0;
    memset(num,0,sizeof(num)); //区间中同种数的个数
    for(int i=0;i<m;i++)
    {
        while(R<M[i].R)
        {
            R++;
            temp-=(long long)num[a[R]]*num[a[R]];
            num[a[R]]++;//a[R]的个数加1
            temp+=(long long)num[a[R]]*num[a[R]];
        }
        while(L>M[i].L)
        {
            L--;
            temp-=(long long)num[a[L]]*num[a[L]];
            num[a[L]]++;//a[L]的个数加1
            temp+=(long long)num[a[L]]*num[a[L]];
        }
        while(R>M[i].R)
        {
            temp-=(long long)num[a[R]]*num[a[R]];
            num[a[R]]--;//a[L]的个数减1
            temp+=(long long)num[a[R]]*num[a[R]];
            R--;
        }
        while(L<M[i].L)
        {
            temp-=(long long)num[a[L]]*num[a[L]];
            num[a[L]]--;//a[R]的个数减1
            temp+=(long long)num[a[L]]*num[a[L]];
            L++;
        }
        ans[M[i].id].a=temp-(R-L+1);
        ans[M[i].id].b=(long long)(R-L)*(R-L+1);
        ans[M[i].id].reduce();
    }
}
int main()
{
    int i,j,k;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        unit=(int)sqrt(n); //总区间分为unit块
        for(i=0;i<m;i++)
        {
            M[i].id=i;
            scanf("%d%d",&M[i].L,&M[i].R);
        }
        sort(M,M+m,cmp); //对询问排序
        work();
        for(i=0;i<m;i++)
        printf("%lld/%lld\n",ans[i].a,ans[i].b);
    }
    return 0;
}
时间: 2024-11-13 22:43:14

HYSBZ 2038 小Z的袜子(hose) (莫队算法入门)的相关文章

HYSBZ 2038 小Z的袜子(hose) (莫队算法)

题意:中文题. 析:很著名的莫队算法,先把这个求概率的式子表达出来,应该是分子:C(x1, 2) + C(x2, 2) + C(x3, 2) + ... + C(xn, 2)  分母:C(n, 2),然后化成分数的表达形式,[x1(x1-1)+x2(x2-1)+...+xn(xn-1)] / (n*(n-1))  然后再化简得到 (sigma(xi*xi)  - n) / (n*(n-1)) ,然后就是对每个区间进行运算,离线,把所以的序列分成sqrt(n)块,然后用两个指针,进行对数据的计算.

bzoj 2038 [2009国家集训队]小Z的袜子(hose) 莫队算法

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 10239  Solved: 4659[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命--具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两

BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只

kyeremal-bzoj2038-[2009国家集训队]-小z的袜子(hose)-莫队算法

bzoj2038-[2009国家集训队]-小z的袜子(hose) F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  Manacher Logout 捐赠本站 Notice:省选季快乐&另求历年World Final数据,谢谢&OJ试题突破3000大关! 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 

bzoj2038 小Z的袜子(hose)——莫队算法

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2038 就是莫队算法: 先写了个分块,惨WA: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; int const maxn=

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

题意:Q个询问,每个询问给定区间[L,R],求从里面任选两个数相同的概率. 思路:莫队算法.用一个cnt数组记录当前区间每种数的个数,区间变化为1时O(1)的维护cnt数组,并可以O(1)的得到当前区间中与当前数相同的数的个数. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48

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

题目链接:点击打开链接 先把询问处理成曼哈顿最小生成树. 然后在树上暴力跑即可. 能使用莫队的情况应该是对于询问[l,r] -> [l', r'] 花费必须是 abs(l-l') + abs(r-r') #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h

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

莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) ------------------------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 50009; int N,

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

题目链接:2038: [2009国家集训队]小Z的袜子(hose) 题目: Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬.你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子

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

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