[CEOI 2025] Equal Mex 题解

news/2025/11/27 19:40:08/文章来源:https://www.cnblogs.com/FloatingLife/p/19279196

[CEOI 2025] Equal Mex

虽然说是套路题,但是记录一下一些结论防止自己以后忘了。

首先不难发现你划分出的每个子段的 \(\operatorname{mex}\) 一定就是整个区间的 \(\operatorname{mex}\),而且 \(k\) 合法 \(k-1\) 也一定合法,所以答案就是能划分的最大段数,不难写出 \(O(nq)\) 的贪心。

然后考虑正解,我们需要若干结论:

结论一:我们称一个区间 \([l,r]\)极小 \(\operatorname{mex}\) 区间当且仅当不存在他的一个子区间 \([l',r']\) 使得 \(\operatorname{mex}[l,r]=\operatorname{mex}[l',r']\)。则极小 \(\operatorname{mex}\) 区间的数量是 \(\le 2n\)(为了避免 corner case 我们不讨论 \(l=r\) 的区间,这些区间的处理是简单的)。

证明:不妨先考虑所有 \(a_l>a_r\) 的区间,对于这样的一个极小 \(\operatorname{mex}\) 区间 \([l,r]\),由于他是极小的,所以 \(\operatorname{mex}[l,r]>a_l>a_r\),否则可以缩减某一个端点,那么:
- 对于一个 \(r'<r,a_{r'}<a_l\)\([l,r']\) 不可能是极小的,因为 \(\operatorname{mex}[l,r']\le a_r < a_l\) 所以增大 \(l\) 不影响区间 \(\operatorname{mex}\)
- 对于一个 \(r'>r,a_{r'}<a_l\)\([l,r']\) 同样不可能是极小的,因为 \(\operatorname{mex}[l,r]>a_l>a_{r'}\) 所以 \(a_{r'}\)\([l,r]\) 出现过了,减小 \(r'\) 不影响区间 \(\operatorname{mex}\)
因此对于每个 \(l\) 只存在一个 \(r\) 满足 \(a_r<a_l\)\([l,r]\) 是极小 \(\operatorname{mex}\) 区间;同理可证对每个 \(r\) 只有一个 \(l\) 满足 \(a_l<a_r\) 且符合条件。

然后是如何 \(O(n\log n)\) 求出所有极小 \(\operatorname{mex}\) 区间:对区间左端点 \(l\) 从小到大扫描线,用 ODT 维护每个 \(r\) 对应的区间 \([l,r]\)\(\operatorname{mex}\)(显然 \(\operatorname{mex}\) 具有单调性,可以用 ODT 维护);每次 \(l\to l+1\) 时,不妨设 \(x\) 是下一个满足 \(a_x=a_l\) 的位置,则我们需要把 \([l,x)\) 末尾的若干 \(\operatorname{mex} > a_l\) 的区间推平成 \(a_l\),如果在这个过程中推平了一个区间 \([l',r']\),那么 \([l,l']\) 就是一个极小 \(\operatorname{mex}\) 区间;我们可以顺便求出每个询问区间的 \(\operatorname{mex}\)
注意: 如果 \([l,x)\) 末尾不存在需要推平的区间,那么你可能需要把 ODT 一开始 split 出的两个区间 merge 回去,因为我们要保证 ODT 中维护的颜色段是极长的,否则求出的极小 \(\operatorname{mex}\) 区间会有问题。

结论二:对于一个区间 \([l,r]\) 总可以找到一个极小 \(\operatorname{mex}\) 区间 \([l',r']\subset [l,r]\) 满足 \(\operatorname{mex}[l',r']=\operatorname{mex}[l,r]\)

我们把所有 \(\operatorname{mex}\) 相同的询问和极小 \(\operatorname{mex}\) 区间放到一起做,于是问题变成找到询问区间内尽可能多的互不相交的极小 \(\operatorname{mex}\) 区间。
显然这是个经典贪心,由于所有极小 \(\operatorname{mex}\) 区间互不包含,所以把这些区间按照左端点排序右端点也升序,先用双指针预处理每个区间跳到的下一个区间,回答询问可以直接倍增。

\(O((n+q)\log n)\),目前最优解第二。

#include<bits/stdc++.h>
#define Debug puts("-------------------------")
#define eb emplace_back
#define pb push_back
#define iter set<P>::iterator 
#define PII pair<int,int>
#define fi first
#define se second 
using namespace std;
const int N=6e5+5,V=4e5+5;
int n,m,a[N],pos[V],nxt[N],ans[N]; 
bool flag[V];
struct Que{ int l,r; } que[N];
vector<int> vec[N];
struct P{ mutable int l,r,c; };
bool operator < (const P&x,const P&y){ return x.l<y.l; }
struct ODT{set<P> S;iter split(int x){if(x==n+1) return S.end();iter it=S.lower_bound({x,0,0});if(it!=S.end()&&(*it).l==x) return it;--it;int l=(*it).l,r=(*it).r,c=(*it).c;S.erase(it),S.insert({l,x-1,c});return S.insert({x,r,c}).first;}int query(int x){iter it=S.lower_bound({x,0,0});if(it!=S.end()&&(*it).l==x) return (*it).c;else return (*prev(it)).c;}void pop_front(){if((*S.begin()).l==(*S.begin()).r) S.erase(S.begin());else (*S.begin()).l++;}
}odt;
int f[25][N];
struct Solve{vector<PII> v;vector<int> q;void work(int mex){if(!q.size()) return;if(mex==1){for(int id:q) ans[id]=que[id].r-que[id].l+1;return;}sort(v.begin(),v.end());int siz=v.size();for(int i=0,j=0;i<siz;i++){while(j<siz&&v[j].fi<=v[i].se) j++;f[0][i]=j;}f[0][siz]=siz;for(int t=1;t<=__lg(siz);t++) for(int i=0;i<=siz;i++) f[t][i]=f[t-1][f[t-1][i]];for(int id:q){int l=que[id].l,r=que[id].r,x=lower_bound(v.begin(),v.end(),make_pair(l,0))-v.begin();ans[id]=1;for(int t=__lg(siz);t>=0;t--)if(f[t][x]<siz&&v[f[t][x]].se<=r) ans[id]+=1<<t,x=f[t][x];			}}
}sub[V];
void Init(){for(int i=n;i>=1;i--) nxt[i]=(pos[a[i]])?pos[a[i]]:(n+1),pos[a[i]]=i;int mex=1,lst=1;for(int i=1;i<=n;i++){flag[a[i]]=true;if(flag[mex]){if(i-1>=lst) odt.S.insert({lst,i-1,mex});lst=i;	}while(flag[mex]) mex++;}odt.S.insert({lst,n,mex});for(int l=1;l<=n;l++){for(int id:vec[l]) sub[odt.query(que[id].r)].q.eb(id);int r=nxt[l];iter itr=odt.split(r);if((*prev(itr)).c<a[l]){if(r!=n+1&&(*prev(itr)).c==(*itr).c){(*itr).l=(*prev(itr)).l;odt.S.erase(prev(itr));} }else{--itr;int L,R=(*itr).r;while(true){sub[(*itr).c].v.pb({l,(*itr).l});if(itr==odt.S.begin()||(*prev(itr)).c<a[l]){L=(*itr).l;odt.S.erase(itr);break;	}--itr,odt.S.erase(next(itr));}odt.S.insert({L,R,a[l]});}odt.pop_front();}
}
vector<int> solve(int N, std::vector<int>& v,int Q, std::vector<std::pair<int, int>>& queries){n=N,m=Q;for(int i=1;i<=n;i++) a[i]=v[i-1];for(int i=1;i<=m;i++) que[i]={queries[i-1].fi,queries[i-1].se},vec[que[i].l].eb(i);Init();for(int i=1;i<V;i++) sub[i].work(i);vector<int> res;for(int i=1;i<=m;i++) res.eb(ans[i]);return res;
}

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

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

相关文章

法语动词变位

忍好久了。 第三组变位怎么这么 tm 烦啊。 今天突发奇想,是不是能让 AI 把我没能力实现的想法实现一下。我去还真可以啊! 那就粘在下面吧~~~ 以后说不定会补充,但也有可能记本子上。 🇫🇷 法语第三组动词变位规…

日总结 32

html5 和flash区别: Flash 核心功能 | HTML5 替代方案 | 说明 矢量动画 / 逐帧动画 | CSS3 动画 / 过渡 + SVG + Canvas | CSS3 做简单动效,SVG 做矢量动画,Canvas 做逐帧 / 复杂动…

2025年11月液体容器磁致伸缩液位计,格雷母线,lvdt位移传感器厂家最新推荐,容器监测与位移适配指南

2025年11月液体容器磁致伸缩液位计、格雷母线、LVDT位移传感器厂家最新推荐在工业生产中,液体容器的监测以及位移适配是保障生产安全与高效运行的重要环节。而杭州浙达精益机电技术股份有限公司(TEC品牌)就是一家在…

2025年11月掘进机位移传感器,拦焦车位移传感器,推焦车位移传感器厂家最新推荐,焦化设备适配测评

2025年11月位移传感器厂家推荐:杭州浙达精益适配焦化设备测评在2025年11月,对于掘进机、拦焦车、推焦车位移传感器的选择,众多厂家中,杭州浙达精益机电技术股份有限公司(TEC品牌)值得重点关注。该公司成立于1993…

2025年11月辊缝位移传感器,切纸位移传感器,水坝闸门液压位移传感器厂家最新推荐,水利与造纸适配测评

2025 年 11 月位移传感器厂家最新推荐:水利与造纸适配测评在工业发展的进程中,辊缝位移传感器、切纸位移传感器以及水坝闸门液压位移传感器等设备发挥着至关重要的作用。这些传感器广泛应用于钢铁、造纸、水利等多个…

2025年11月起重机位移传感器,挖掘机位移传感器,压路机位移传感器厂家最新推荐,工程机械性能测评

《2025年11月工程机械位移传感器厂家推荐与性能考量》在2025年11月,对于起重机、挖掘机、压路机等工程机械而言,位移传感器的选择至关重要。一个优质的位移传感器能显著提升工程机械的性能和可靠性。而杭州浙达精益机…

Java大厂面试真题:Spring Boot微服务+Kafka消息队列+AIGC场景实战问答全解析 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

从被动审查到主动风控:文档抽取技术驱动合同管理范式转移

当一份合同历经多轮谈判,产生数个修订版本后,如何确保最终版没有遗漏关键修改?如何快速洞察条款表述的细微变化背后隐藏的法律风险?在传统的“人眼扫描”式比对方式下,这些挑战不仅极度耗费专业人力,更构成了企业…

Python中isdigit、isdecimal、isnumeric区别详解

Python中isdigit、isdecimal、isnumeric区别详解【Python入门教程】第88篇 常用字符串方法之字符类型检查本博客是博主个人学习时的一些记录,不保证是为原创,个别文章加入了转载的源地址,还有个别文章是汇总网上多份…

3D 场景预加载应用实现 | 图扑软件

预加载是在进入正式场景之前提前加载所需模型、材质、图片等资源的技术手段,其核心价值在于消除资源加载等待,确保场景首次渲染即可完整呈现,从而提供无缝、流畅的用户体验。在复杂的 Web 3D 可视化应用中,资源预加…

2025年11月GEO公司推荐:全链路破局企业流量困境,AI驱动搜索优化实力全解析

在生成式 AI 重塑搜索生态的浪潮下,AI 搜索与 GEO 优化已成为企业争夺数字流量的核心战略。《2025 中国生成式 AI 搜索生态白皮书》显示,2025 年第三季度相关服务市场规模超 220 亿元,企业采用率同比激增 147%。但行…

CH584/CH585NFC调试相关

在NFC调试中不同线圈对应的匹配参数大概率不一样,刷卡的效果的表现不一。在打板画线圈的时候就要根据沁恒提供的NFC手册及实际版上空间去绘制线圈。绘制线圈的时候要注意线圈的自感要在1-1.5uh左右(计算公式可见手册…

租房买房必看2租房切忌“暗室”!这种房子阴气重、易生病,白送都别住!

2 租房切忌“暗室”!这种房子阴气重、易生病,白送都别住! 2.1 房子便宜是有原因的! 在找房的过程中,你是否遇到过这样的情况: 地段不错,装修尚可,租金却比周边便宜一大截? 这时候请务必警惕!走进屋里看看,是…

人工智能之数据分析 Matplotlib:第二章 Pyplot

人工智能之数据分析 Matplotlib:第二章 Pyplot人工智能之数据分析 Matplotlib 第二章 Pyplot@目录人工智能之数据分析 Matplotlib前言一、导入方式二、基本用法示例1. 绘制简单折线图2. 多条曲线 & 图例3. 散点图…

医疗器械渠道管理革新:数字化平台如何解决行业痛点

医疗器械行业的信息化水平相较其他行业明显滞后,大量业务仍依赖纸质单据、Excel、邮件及散乱的即时通讯工具。这种模式导致流程不可见、无提醒、无追溯,人员投入大却效率低下。在带量采购成为常态的背景下,医疗器械…

性能验证问题汇总

QSPI-Flash启动时,取指速度慢 背景知识:外挂Flash支持通过QSPI接口挂接;支持从QSPI Flash启动;QSPI Flash支持2线、4线读写;直接从Flash取值,速度比较慢,一般通过以下两种方法加速为外挂Flash增加cache 使能QSP…

如何在VSCode中Debug(带有参数,name、program、$file、args、pickArgs、指定虚拟环境)

如何在VSCode中带有参数的Debug(name、program、$file、args、pickArgs、指定虚拟环境) 0. 省流 {"version": "0.2.0","configurations": [{"name": "调试train.py文件…

深入解析:Android Cursor AI实践技巧

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

C# 中的安全零拷贝

C#中使用Span或者ReadOnlySpan实现安全零拷贝操作英文链接Safe zero-copy operations in C#C# 中的安全零拷贝 Sedat Kapanoglu 塞达特卡帕诺卢 29 Sep 2025 My attempt at talking about one of the most underrated …

适合应届生:零经验专业简历模板TOP4

对于即将踏入职场的应届毕业生而言,最头疼的莫过于“零经验”这一挑战。如何在简历中巧妙展现自身潜力,赢得HR的青睐?选择一款合适的简历制作工具显得尤为重要。 本文将为您盘点值得应届生信赖的四大简历模板工具,…