首页 > 其他分享 >2023NOIP A层联测22 差后队列

2023NOIP A层联测22 差后队列

时间:2023-11-01 22:58:36浏览次数:35  
标签:cnt 差后 22 int st maxn ans 2023NOIP mod

2023NOIP A层联测22 差后队列

挺有意思的期望题,题解做法应该是 DP,但是我又双叒写出奇怪的做法……

思路

除去最大值外的元素个数的倒数就是这一轮取到某个数的概率,而最大值是特殊的情况,在被替代之前或作为最后一个数被弹出之前,不参与计算。

对于操作 0 的输出和操作 1 的输出分开处理。

操作 1

设 \(f[i]\) 表示在执行第 \(i\) 个操作时可弹出数的期望大小。

1.加入操作

加入后不成为最大值,\(f[i]=f[i-1]+val[i]\)。

加入后成为最大值,\(f[i]=f[i-1]+mx\),然后更新 \(mx=val[i]\)。(\(mx\) 为最大值)

2.删除操作

设此时队列中除去最大值外元素个数为 \(has\)。

除最大值外每个元素被取到的概率 \(p=\frac{1}{has}\)。

此时期望取到的值 \(ans=p*f[i]\)。

更新 \(f[i]=f[i-1]-ans\)。

\(ans\) 为这一次操作的答案。

操作 0

不难发现,每个元素都有一个开始会被弹出的操作 1,和一定被弹出队列的操作 1。

设第 \(i\) 个弹出操作弹出每个树的概率是 \(p[i]\)。(除最大值外每一个数被等概率弹出,所以 \(p[i]\) 容易得到)

设第 \(i\) 个弹出操作是总操作中第 \(a[i]\) 个操作。

设第 \(u\) 个插入队列的数,可以被弹出的第一个操作 1 是总弹出操作第 \(st_u\) 个,一定会被弹出的操作 1 是总弹出操作的第 \(ed_u\) 个。

那么对于第 \(u\) 个插入的数。如果不是最大值,那么它在第 \(k\ (st_u \leq k \leq ed_u)\) 次操作被弹出的概率是 \(p_k\prod_{j=st_u}^{k-1}(1-p_j)\)。

给期望删除时间的贡献为 \(a_kp_k\prod_{j=st_i}^{k-1}(1-p_j)\)。

第 \(u\) 个插入的数被删除时间的期望为 \(ans_u=\sum_{i=st_u}^{ed_u} a_ip_i \prod_{j=st_u}^{i-1} (1-p_j)\)。

接下来要考虑如何 \(O(1)\) 的求这个式子。

设 \(s_i=a_ip_i\prod_{j=1}^{i-1}(1-p_j)\)。

又有 \(g_1=\frac{1}{1-p_1}\),\(g_i=g_{i-1}\frac{1}{1-p_i}\)。

所以 \(ans_u=\sum_{i=st_u}^{ed_u} s_ig_{st_u-1}=g_{st_u-1}\sum_{i=st_u}^{ed_u} s_i\)。

后面的 \(s_i\) 可以用前缀和 \(O(1)\) 求出。

而上面的数预处理都是 \(O(n)\) 或 \(O(n\log_2n)\)。

总时间复杂度 \(O(n\log_2n)\)。

可能会有点小常数。

CODE

#include<bits/stdc++.h>
using namespace std;

#define mod 998244353
#define int long long

const int maxn=1e6+5;

struct node
{
    int st,ed;
}point[maxn];

int cnt,n,has=-1,mx,smx;
int a[maxn],val[maxn],p[maxn],s[maxn],f[maxn],g[maxn],ans[maxn],sp[maxn],t[maxn],st[maxn],ed[maxn];

queue<int>que;

int ksm(int x,int y)
{
    int sum=1;
    for(;y;y/=2,x=x*x%mod) if(y&1) sum=sum*x%mod;
    return sum;
}

signed main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        int op;
        scanf("%lld",&op);
        if(op==0)
        {
            scanf("%lld",&val[i]);
            has++;
            if(val[i]>mx)
            {
                f[i]=(f[i-1]+mx)%mod,mx=val[i],st[smx]=cnt+1;
                if(smx) que.push(smx);
                smx=i;
            }
            else f[i]=(f[i-1]+val[i])%mod,st[i]=cnt+1,que.push(i);
        }
        else
        {
            cnt++;
            if(has)
            {
                p[cnt]=ksm(has,mod-2);
                a[cnt]=i;
                ans[i]=f[i-1]*p[cnt]%mod;
                f[i]=(f[i-1]-ans[i]+mod)%mod;
            }
            else
            {
                p[cnt]=1;
                a[cnt]=i;
                ans[i]=mx;
                ans[smx]=i;
                mx=smx=0;
                f[i]=0;
            }
            has--;
            if(has==0) while(!que.empty()) ed[que.front()]=cnt,que.pop();
        }
    }
    while(!que.empty()) ed[que.front()]=cnt,que.pop();

    sp[0]=1;
    for(int i=1;i<=cnt;i++) sp[i]=max(sp[i-1]*((1-p[i]+mod)%mod)%mod,1ll);
    for(int i=1;i<=cnt;i++) s[i]=sp[i-1]*p[i]%mod*a[i]%mod,t[i]=(t[i-1]+s[i])%mod;
    g[0]=1;
    for(int i=1;i<=cnt;i++)
    {
        if(p[i]==1) g[i]=1;
        else g[i]=g[i-1]*ksm((1-p[i]+mod)%mod,mod-2)%mod;
    }
    for(int i=1;i<=n;i++)
    {
        if(ans[i]||val[i]==0||ed[i]==0||st[i]==0||ed[i]<st[i]||ed[i]>cnt) continue;
        ans[i]=(t[ed[i]]-t[st[i]-1]+mod)*g[st[i]-1]%mod;
    }
    for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
}

还是挺浅显易懂的吧。

标签:cnt,差后,22,int,st,maxn,ans,2023NOIP,mod
From: https://www.cnblogs.com/binbinbjl/p/17804326.html

相关文章

  • P8424 [JOI Open 2022] 跷跷板(Seesaw)
    Description一根长度为\(10^9\)的直杆从左到右水平放置。你可以忽略这根杆的重量。共有\(N\)个砝码挂在这根杆上,每个砝码的质量为一单位。这\(N\)个砝码的位置两两不同。第\(i(1\leqi\leqN)\)个砝码的位置为\(A_i\)。即,第\(i\)个砝码到直杆最左端的距离为\(A_i\)......
  • 洛谷 P2290 [HNOI2004] 树的计数(Prufer序列,Cayley 公式)
    传送门解题思路关于Prufer序列的构造,见OI-wiki这里直接放结论:一个Prufer序列与一个无根树一一对应度数为\(d_i\)的节点在序列中出现了\(d_i-1\)次\(\sum(d_i-1)=n-2\)n个点的完全图的生成树有\(n^{n-2}\)种所以相当于n-2个数(有重复的)进行全排列,答案即为:\[\frac......
  • NOIP 模拟8(NOIP A层联测22)
    \(100+100+40+0\),T3卡时没卡对挂了\(20\)。后来发现赛时T3是时间复杂度和正确性都是对的,只是常数大导致我以为它跑不出来。A.集合给定一个序列,求有多少个子区间满足这个区间的数的集合的所有值域连续段长度都不超过\(k\)。答案满足单调性,双指针统计答案,权值线段树维护最......
  • 洛谷P3522/POI2011 TEM-Temperature
    涉及知识点:单调队列、贪心、递推前言最近找了点单调队列的题练练手,就遇到这道题,本题对于单调队列弹队尾的时候有别于普通单调队列,一些题解并没有写的很清楚,因此写下这篇题解。题面Link你有一个长度为\(n\)的序列\(A\),告诉你序列中每一个数\(A_i\)的取值范围\(down_i\)......
  • 22 RSTP(Rapid STP/快速生成树)
    随着局域网规模的不断增长,STP拓扑收敛速度慢的问题逐渐凸显,因此,IEEE在2001年发布了802.1W标准,定义了RSTP(RapidSpanningTreeProtocol,快速生成树协议),RSTP在STP的基础上进行了改进,可实现网络拓扑的快速收敛。STP不足之处STP对计时器的依赖初始化场景STP采用计时器防止临时......
  • 2022 CSPJ
     直接模拟即可,注意特判#include<iostream>#include<cstdio>#include<ctime>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#definemaxn200010#defineLLlonglongusingnamespacestd;intmain(){......
  • Visual Studio 2022使用总结
    如何让新建的文件默认为utf8编码点击扩展,管理扩展,搜索utf8,选择ForceUTF-8(WithBOM)2022,安装后重启即可。注意:这里还有一个NoBOM版本,但是该版本的编码在VisualStudio2022下输出中文会报错。经历:我在windows下写好的cpp文件,在linux编译后运行发现中文乱码,后来发现linux显......
  • 【Redis】Ubuntu22.04安装Redis
    Redis数据库安装前言:最近想要学习用Python控制Redis的方法,但是Redis官网是不支持Windows直接安装的,各种大佬的Windows移植版本也比较老,虽然够用,但是也希望使用官网版本。网上的各种安装教程或多或少都存在一点问题,这里我针对我所使用的服务器版本安装Redis服务进行整理,若与我采......
  • 【专题】2022年中国财税数字化行业研究报告PDF合集分享(附原数据表)
    数字化是复杂系统中的一个重要驱动因素,它得到了技术进步的支持。随着以大数据、物联网、云计算、人工智能等为代表的数字技术的不断成长和成熟,企业必须应对的内外部环境发生了翻天覆地的变化。新的全球生产力革命的一个关键驱动因素是数字智能化。企业的采购、生产、经营、销售等商......
  • C#编程工具Visual Studio2022新特性(持续。。。)
    VS从2017年开始变动比较大,目前最新的版本是2022年版,框架也比之前的高级一丢丢,如果是老用户,可能对它的新特性还不是很习惯,跟着我一起对VS2022新特性进行深入探索:一、之前的编码模板的改变(对比)在VS2022中如果要切换到旧版本模板呢,你可以在创建项目时选择“.NETFramework”项目......