P10587 「ALFR Round 2」C 小 Y 的数

news/2025/1/5 14:45:24/文章来源:https://www.cnblogs.com/peiwenjun/p/18649388

题目描述

给定长为 \(n\) 的序列, \(m\) 次操作:

  • 1 l r x :将 \(l\sim r\) 中的数加上 \(x\)
  • 2 l r x :将 \(l\sim r\) 中的数乘上 \(x\)
  • 3 l r x :将 \(l\sim r\) 中的数修改为 \(x\)
  • 4 l r x :询问 \(l\sim r\)\(42,424,4242,42424,424242\) 出现次数之和。

数据范围

  • \(1\le n,m\le 5\cdot 10^5\)
  • \(1\le l\le r\le n,1\le a_i,x\le 5\cdot 10^5\) ,保证任意时刻 \(1\le a_i\le 5\cdot 10^5\)

时间限制 \(\texttt{700ms}\) ,空间限制 \(\texttt{64MB}\)

分析

先考虑如果只询问 \(M\) 的出现次数怎么做。

定义势能 \(\varphi\) 为线段树所有节点对应的区间中不超过 \(M\) 的数的个数之和,初始 \(\varphi=n\log n\)

对于操作 \(1,2\)\(\varphi\) 不增;对于操作 \(3\) ,将完全相同的区间视为单点, \(\varphi\) 至多增加 \(\mathcal O(\log n)\)

判断完全相同只需维护区间最大最小值。

对线段树每个节点维护 \(val=\max\limits_{[l,r]}[a_i\le M]a_i\) ,加乘直接对 \(val\) 打标记,如果 \(val\gt M\) 则递归下去修改。

回答询问只需顺便维护 \(val\) 的出现次数 \(cnt\) ,如果 \(val=M\) 则贡献为 \(cnt\) ,否则为零。

递归时我们花费 \(1\) 单位的代价使 \(\varphi\) 减少 \(1\) ,时间复杂度 \(\mathcal O((n+m)\log n)\)


同时开 \(5\) 棵线段树就做完了?抱歉,空间不够。

如果还想维护某个变量支持加乘操作,还能判断区间内是否某个位置越过了询问的数,容易发现这是做不到的。

退而求其次,注意到值域很小,所以乘法次数不会很多,直接暴力做。对于加法,记 \(nxt_i\)\(i\) 到下一个(\(\ge i\))询问的数的距离,对线段树每个节点维护 \(val=\min nxt_{a_i}\) ,加法和覆盖操作可以套用上面的做法。

于是我们需要重新定义势能:

  • \(\varphi_1\) 表示线段树所有区间中大于 \(a_i\) 的询问的数个数之和。
  • \(\varphi_2\) 表示线段树所有区间 \(\sum\lfloor\log a_i\rfloor\) 之和。

初始 \(\varphi_1=5n\log n,\varphi_2=n\log n\log V\)

对于加法操作,花费 \(1\) 的代价使 \(\varphi_1\) 减小 \(1\) ,同时 \(\varphi_2\) 不增。

对于乘法操作,花费 \(1\) 的代价使 \(\varphi_2\) 减小 \(1\) ,同时 \(\varphi_1\) 不增。

对于覆盖操作, \(\varphi_1\) 增加 \(5\)\(\varphi_2\) 增加 \(\log V\)

时间复杂度 \(\mathcal O((n\log n+m)(5+\log V))\)

#include<bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int maxn=5e5+5;
int m,n;
int key[6]={42,424,4242,42424,424242,500001};
int a[maxn],nxt[maxn];
struct node
{int l,r;int mn,mx,cnt,val;///val=min nxtint add,cov;
}f[maxn<<2];
int read()
{int q=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while(isdigit(ch)) q=10*q+ch-'0',ch=getchar();return q;
}
void pushup(int p)
{f[p].mn=min(f[ls].mn,f[rs].mn);f[p].mx=max(f[ls].mx,f[rs].mx);f[p].val=min(f[ls].val,f[rs].val);f[p].cnt=(f[p].val==f[ls].val?f[ls].cnt:0)+(f[p].val==f[rs].val?f[rs].cnt:0);
}
void pushcov(int p,int x)
{f[p].mn=f[p].mx=x,f[p].val=nxt[x],f[p].cnt=f[p].r-f[p].l+1,f[p].cov=x,f[p].add=0;
}
void pushadd(int p,int x)
{if(f[p].cov) return pushcov(p,f[p].cov+x);assert(x<=f[p].val);f[p].mn+=x,f[p].mx+=x,f[p].val-=x,f[p].add+=x;
}
void pushdown(int p)
{assert(!f[p].cov||!f[p].add);if(f[p].cov) pushcov(ls,f[p].cov),pushcov(rs,f[p].cov),f[p].cov=0;if(f[p].add) pushadd(ls,f[p].add),pushadd(rs,f[p].add),f[p].add=0;
}
void build(int p,int l,int r)
{f[p].l=l,f[p].r=r;if(l==r) return f[p].mn=f[p].mx=a[l],f[p].val=nxt[a[l]],f[p].cnt=1,void();int mid=(l+r)>>1;build(ls,l,mid),build(rs,mid+1,r);pushup(p);
}
void modify_a(int p,int l,int r,int x)
{if(l>f[p].r||r<f[p].l) return ;if(l<=f[p].l&&f[p].r<=r){if(f[p].mn==f[p].mx) return pushcov(p,f[p].mn+x);if(x<=f[p].val) return pushadd(p,x);}pushdown(p);modify_a(ls,l,r,x),modify_a(rs,l,r,x);pushup(p);
}
void modify_m(int p,int l,int r,int x)
{if(x==1||l>f[p].r||r<f[p].l) return ;if(l<=f[p].l&&f[p].r<=r&&f[p].mn==f[p].mx) return pushcov(p,f[p].mn*x);pushdown(p);modify_m(ls,l,r,x),modify_m(rs,l,r,x);pushup(p);
}
void modify_c(int p,int l,int r,int x)
{if(l>f[p].r||r<f[p].l) return ;if(l<=f[p].l&&f[p].r<=r) return pushcov(p,x);pushdown(p);modify_c(ls,l,r,x),modify_c(rs,l,r,x);pushup(p);
}
int query(int p,int l,int r)
{if(l>f[p].r||r<f[p].l) return 0;if(l<=f[p].l&&f[p].r<=r) return !f[p].val?f[p].cnt:0;pushdown(p);return query(ls,l,r)+query(rs,l,r);
}
int main()
{n=read(),m=read();for(int i=1;i<=n;i++) a[i]=read();for(int i=1;i<=5e5;i++)for(int j=5;j>=0;j--)if(i<=key[j]) nxt[i]=key[j]-i;build(1,1,n);while(m--){int op=read(),l=read(),r=read();if(op==1) modify_a(1,l,r,read());if(op==2) modify_m(1,l,r,read());if(op==3) modify_c(1,l,r,read());if(op==4) printf("%d\n",query(1,l,r));}return 0;
}

总结

  • 本题卡 scanf ,必须快读。

  • 标记合并是永远的难点。由于 cov 优先级比 add 高,所以如果 cov 标记存在,区间加要转化为区间覆盖操作。

  • 惨痛的 debug 经历:

    博主在第 \(55\) 行后加上了这样一句话 if(f[p].l==f[p].r) return f[p].mn+=x,f[p].mx+=x,f[p].val=nxt[f[p].mn],void(); ,然后报错信息都出在几千行的位置。再加上本题数据超级难造(纯随机小数据输出全是零,大数据很难保证值域范围),调了一个多小时。

    后来发现 cov 标记也要更新,因为头顶的 add 标记推到这里会转化为区间覆盖,需要用到 cov 标记的值。

    一般情况下标记都是打给下一层的,但是本题我们需要用 cov 标记反推这一层的信息,总之非常魔幻就对了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/863254.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鲲鹏服务器屏蔽告警的方法

描述:工程现场发现设备开启snmp v2c后会有不安全协议告警,且客户侧纳管平台会一直存在这个告警。解决:手动干预进行告警屏蔽ipmitool raw 0x30 0x90 0x58 0x01 0x00 0x06 0x00 0x49 0x00 0x00 0x1A 0x00 0x02已知故障码是0x1A000049,而上面标红部分是故障码0x49 0x00 0x00 …

谷歌为什么将在2025年主导人工智能

谷歌通往AI霸主地位的路径图片由谷歌Imagen 3生成2023年2月6日,谷歌首席执行官桑达尔皮查伊在巴黎登台,展示了谷歌的首款AI驱动聊天机器人Bard。 Bard出现了“幻觉”。 演示失败了,谷歌母公司Alphabet市值蒸发了1000亿美元。 在2023年的大部分时间里,谷歌似乎在人工智能创新…

window redis注册为服务

1.将redis安装目录添加到环境变量中 2.在redis安装目录执行如下命令: redis-server.exe --service-install redis.windows.conf --loglevel verbose 3.成功后,即可在服务列表中查看到该服务 抱怨有用的话还要努力干什么

linux 优化网卡队列

RSS(Receive-Side Scaling)网卡的多队列负载分流技术为了更好的利用多核系统。可以将网卡的数据流分配到多个rx queue,多个队列再分配到多个CPU核上,多个CPU并 行处理数据包,大大提升网络处理能力。但是有可能造成同一个网络会话被分配到多 个rx queue上,导致应用层处理会…

Nginx-WMware安装 c

CentOS-7-x86_64-Minimal-1810.iso镜像下载地址 通过网盘分享的文件:CentOS-7-x86_64-Minimal-1810.iso 链接: https://pan.baidu.com/s/1As2tckziAeVVF7sNJkZSlA?pwd=sky1 提取码: sky1 一、新建虚拟机二、选择 “典型”三、选择刚刚下载的 CentOS-7-x86_64-Minimal-1810的I…

读数据保护:工作负载的可恢复性24磁带和其他

磁带和其他1. 速度不匹配 1.1. 磁带机的速度曾经比备份数据的生成速度慢,而且那时磁带机的速度也比网络速度要慢 1.2. 备份行业就把磁带上的磁位排得比原来更加紧密 1.2.1. 磁位排得密,意味着磁带在不增加长度的情况下能够存储更多的数据 1.2.2. 磁位紧密,同时还意味着磁头在…

宝塔Linux专业版后台帝国CMS更新栏目出现404错误怎么办?

在使用宝塔Linux专业版管理多个站点时,可能会遇到帝国CMS更新栏目时出现404错误的问题。这类问题往往会给日常运维带来不便,因此我们需要仔细分析原因并采取有效的解决措施。以下是详细的解决方案:检查PHP版本兼容性:首先,确认帝国CMS所依赖的PHP版本是否与当前服务器环境…

如何选择适合的云主机配置以满足网站流量需求?

您好,关于您提到的如何选择适合的云主机配置以满足网站流量需求的问题,我们可以从多个角度进行详细探讨,帮助您做出最优选择。 首先,根据您提供的数据(IP 3万多,PV 5万左右,流量每天不到5G),我们来分析一下这些指标对服务器配置的具体要求:CPU和内存:对于日均IP访问…

如何重置虚拟主机/数据库的账号名和密码?

您好,关于您提到的重置虚拟主机或数据库的账号名和密码的问题,这是一个非常重要的操作,涉及到系统的安全性和可用性。以下是详细的步骤和注意事项,帮助您顺利完成重置过程:明确重置对象:首先,请确认您需要重置的具体对象是虚拟主机的管理账号还是数据库的登录凭证。不同…

如何解决SMTP发件被限制的问题?

您好,关于您提到的SMTP发件被限制的问题,这种情况通常是出于安全考虑,以防止滥用邮件服务发送垃圾邮件或恶意邮件。以下是详细的解决方案和建议,帮助您恢复正常发送邮件的功能:理解SMTP限制的原因:SMTP(简单邮件传输协议)是电子邮件系统应用层协议,主要用于发送电子邮…

如何更换网站域名并确保后台访问使用新域名?

在进行任何更改之前,请务必对现有的网站文件和数据库进行全面备份。这可以防止在操作过程中出现意外情况导致数据丢失。您可以通过控制面板或FTP工具下载所有网站文件,并导出数据库备份。修改DNS解析记录: 登录到您的域名注册商账户,找到的DNS设置页面。添加一条A记录指向服…

服务器出现502错误的原因及解决方案

当您遇到服务器出现502错误时,这通常是由于Web服务器与后端应用服务器之间的通信失败引起的。为了帮助您准确诊断并解决问题,以下是详细的排查步骤和解决方案:检查Web服务器日志: Web服务器日志是排查502错误的重要依据。通过查看Apache或Nginx的日志文件,您可以了解具体的…