• P1494 [国家集训队]小Z的袜子(莫队)


    题目链接:https://www.luogu.org/problemnew/show/P1494

    题目大意:中文题目

    具体思路:计算概率的时候,每一次是区间的移动,每一次移动,记得先将原来的记录的影响去掉,然后再加上新的值,每一次这样统计就可以了。然后计算概率的时候就是C(n,2),总的概率的计算方法,当前的颜色是的个数是t,然后就是C(t,2)。总的概率就是C(r-l+1,2),这里的r-l+1指的是当前要求的区间的长度。所以,合法的区间就是C(t,2)/C(r-l+1,2).

    注意特判l==r的情况。

    注意在减去原来的值的影响的时候,不能特判当前的值是不是大于2的,打个比方,原来的当前的值出现的是两次,我们先减去1,然后当前的值变成了1,这个时候我们按道理是需要将原来的影响给删掉,如果特判是不是大于等于2的话,就不可能减去了。

    AC代码:

     1 #include<iostream>
     2 #include<stack>
     3 #include<cstring>
     4 #include<iomanip>
     5 #include<stdio.h>
     6 #include<cmath>
     7 #include<algorithm>
     8 #include<vector>
     9 using namespace std;
    10 # define ll long long
    11 const int maxn = 2e5+100;
    12 ll a[maxn],vis[maxn];
    13 struct node{
    14 ll l,r,pos,id;
    15 bool friend operator < (node t1,node t2){
    16 if(t1.pos==t2.pos)return t1.r<t2.r;
    17 return t1.pos<t2.pos;
    18 }
    19 }q[maxn];
    20 struct qq{
    21 ll t1,t2;
    22 }ans[maxn];
    23 int main(){
    24 // freopen("hqx.in","r",stdin);
    25 ll n,m;
    26 scanf("%lld %lld",&n,&m);
    27 ll block=(ll)sqrt(n);
    28 for(ll i=1;i<=n;i++){
    29 scanf("%lld",&a[i]);
    30 }
    31 for(ll i=1;i<=m;i++){
    32 scanf("%lld %lld",&q[i].l,&q[i].r);
    33 q[i].id=i;
    34 q[i].pos=(q[i].l-1)/block+1;
    35 }
    36 sort(q+1,q+m+1);
    37 ll tmp=0;
    38 ll l=1,r=0;
    39 for(ll i=1;i<=m;i++){
    40 while(l<q[i].l){vis[a[l]]--;
    41 tmp-=(vis[a[l]]+1)*vis[a[l]];
    42 tmp+=vis[a[l]]*(vis[a[l]]-1);
    43 l++;
    44 }
    45 while(l>q[i].l){l--;vis[a[l]]++;
    46 tmp-=(vis[a[l]]-1)*(vis[a[l]]-2);
    47 tmp+=vis[a[l]]*(vis[a[l]]-1);
    48 }
    49 while(r<q[i].r){
    50 r++;vis[a[r]]++;
    51 tmp-=(vis[a[r]]-1)*(vis[a[r]]-2);
    52 tmp+=vis[a[r]]*(vis[a[r]]-1);
    53 }
    54 while(r>q[i].r){
    55 vis[a[r]]--;
    56 tmp-=(vis[a[r]]+1)*(vis[a[r]]);
    57 tmp+=(vis[a[r]]*(vis[a[r]]-1));
    58 r--;
    59 }
    60 if(q[i].l==q[i].r){
    61 ans[q[i].id].t1=0;
    62 ans[q[i].id].t2=1;
    63 continue;
    64 }
    65 ans[q[i].id].t1=tmp;
    66 ans[q[i].id].t2=(q[i].r-q[i].l+1)*(q[i].r-q[i].l);
    67 }
    68 for(ll i=1;i<=m;i++){
    69 ll tmp=__gcd(ans[i].t1,ans[i].t2);
    70 if(ans[i].t1/tmp>ans[i].t2/tmp)printf("1/1
    ");
    71 else
    72 printf("%lld/%lld
    ",ans[i].t1/tmp,ans[i].t2/tmp);
    73 }
    74 return 0;
    75 }
  • 相关阅读:
    JavaScript作用域学习笔记
    Object.prototype.toString.call() 区分对象类型
    oracle 经典SQL整理
    day31
    ID3决策树
    C# 中浅拷贝与深拷贝区别
    C#值类型和引用类型的区别
    C#守护进程(windows服务)
    C#线程池
    C#双缓冲绘图
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10490541.html
Copyright © 2020-2023  润新知