洛谷题单指南-线段树的进阶用法-P4587 [FJOI2016] 神秘数

news/2025/1/10 17:35:56/文章来源:https://www.cnblogs.com/jcwy/p/18640370

原题链接:https://www.luogu.com.cn/problem/P4587

题意解读:对于序列a[n],查询m个区间[l,r]数值对应集合的神秘数。集合 S 的神秘数定义为最小的不能被 S 的子集的和表示的正整数。

解题思路:

对于区间[l,r],从小到大将数值选入集合,来观察神秘数的变化,设S当前的神秘数为ans。

当下一个要选入的数为x时,

  如果x > ans,加入x也不会影响集合的神秘数,ans不变。

    因为,x加入前,S子集和可以表示出[1,ans-1]的数,x>ans,仍然无法表示出等于ans的数;

    所以,S的神秘数还是ans。

  如果x <= ans,加入x会影响集合的神秘数,ans = x + ans。

    加入x前,S子集和表示的数范围是[1,ans-1],加入x后可以表示范围多了[x+1,x+ans-1],再算上x自己;

    加入x后,S子集和表示数的范围变成[1,ans-1] ∪ [x] ∪ [x+1,x+ans-1] = [1,x+ans-1];

    所以ans变成x + ans。   

这样,可以通过将[l,r]范围的数值从小到大选入集合S,ans不断更新,得到最终结果,总体时间复杂度O(mn)。

如何优化?

设集合S当前已选入数都没有超过maxs,也就是下一个加入集合的数必须>=maxs+1,当前神秘数为ans。

不难分析得到,下一个要选入的数,必须再[maxs+1, ans]范围内,才能影响ans,因为<=maxs的数已经加入过了。

那么,[maxs+1, ans]范围的数对神秘数ans的影响是什么呢?

  假设[maxs+1, ans]范围有三个数x,y,z,满足maxs+1<=x<y<z<=ans

  对于x,maxs变成x,神秘数变成x+ans

  对于y,maxs变成y,神秘数变成x+y+ans

  对于z,maxs变成ans(<=ans的数都被选完了),神秘数变成x+y+z+ans

根据以上分析,[maxs+1, ans]范围的数对神秘数的影响就是神秘数变成[maxs+1, ans]数值和sum+ans,之后maxs变成ans。

当前,神秘数要改变,前提是[maxs+1, ans]范围和不为0,如果为0,就得到了最终的神秘数。

用范围求和来代替一个一个的加入集合过程,时间复杂度得到了优化。

因此,本题核心流程用形式化的描述为:

在[l,r]范围查询值域区间[maxs+1,ans]的和res,初始maxs=0,ans=1

持续处理,如果res>0,mas=ans,ans=res+ans

直到res==0,输出ans。

要实现[l,r]范围内的[mas+1,ans]区间和查询,可以采用可持久化线段树。

尽管数值的取值范围较大,不提前build线段树,借助于动态开点,就不需要进行离散化处理。

对于序列1 2 4 9 10动态开点建立的线段树如图所示,请自行比较与提前build再复制的区别,参考:https://www.cnblogs.com/jcwy/p/18630532

100分代码:

#include <bits/stdc++.h>
using namespace std;const int N = 100005;
struct Node
{int L, R; //左、右子节点编号int sum;
} tr[N * 32];
int root[N], idx; //根节点,节点编号
int a[N], maxa;
int n, m;//在根为pre的权值线段树中,将节点[x,x]到根节点复制一份,并把所有sum增加一个x
int update(int pre, int l, int r, int x)
{int u = ++idx;tr[u].L = tr[pre].L;tr[u].R = tr[pre].R;tr[u].sum = tr[pre].sum + x;if(l == r) return u;int mid = l + r >> 1;if(x <= mid) tr[u].L = update(tr[pre].L, l, mid, x);else tr[u].R = update(tr[pre].R, mid + 1, r, x);return u;
}//在left,right权值线段树中,查询值域范围[vl,vr]的元素之和
int query(int left, int right, int l, int r, int vl, int vr)
{if(l >= vl && r <= vr) return tr[right].sum - tr[left].sum;else if(l > vr || r < vl) return 0;else {int mid = l + r >> 1;return query(tr[left].L, tr[right].L, l, mid, vl, vr) + query(tr[left].R, tr[right].R, mid + 1, r, vl, vr);}
}int main()
{cin >> n;for(int i = 1; i <= n; i++){cin >> a[i];maxa = max(maxa, a[i]);}for(int i = 1; i <= n; i++) root[i] = update(root[i - 1], 1, maxa, a[i]);cin >> m;int l, r;while(m--){int maxs = 0, ans = 1, res;cin >> l >> r;while(true){res = query(root[l - 1], root[r], 1, maxa, maxs + 1, ans);if(!res) break;maxs = ans, ans = res + ans;}cout << ans << endl;}return 0;
}

 

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

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

相关文章

pandas-Series

一、Series特点 二、特点练习import pandas as pd import numpy as np #pandas---Series#默认索引从0开始且数组类型数据 data=np.array([张三,李四,王五,赵六]) s=pd.Series(data) print(s)#自定义索引 s=pd.Series(data,index=[100,101,102,103],name=series_name) print(s)…

软件系统验收全流程解析:从准备到后续保障,关键要点一览

验收准备阶段确定验收标准:在项目启动初期,就应根据项目需求和合同约定,制定详细的验收标准。验收标准应涵盖功能、性能、安全、兼容性、易用性等各个方面,确保软件系统满足用户的业务需求和预期。 组建验收团队:验收团队通常由用户方代表、项目负责人、技术专家、测试人员…

CDS标准视图:维护活动类型 I_MaintenanceActivityType

视图名称:维护活动类型 I_MaintenanceActivityType 视图类型:基础 视图代码:点击查看代码 @ObjectModel.supportedCapabilities: [ #ANALYTICAL_DIMENSION, #EXTRACTION_DATA_SOURCE, #CDS_MODELING_ASSOCIATION_TARGET,#SQL_DATA_SOURCE, #CDS_MODELING_DATA_SOURCE ]@Meta…

封闭几何形状中的静压液位测量——填充高度的计算

与开口容器不同,封闭几何形状(例如气密罐或者加压容器)中的液位计算需要通过静水压力测量来补偿封闭在液体上方的气体的压力。 对于封闭或加压环境下的液位测量,非通风的容器中的液位测量需要通过第二压力变送器对封闭的气体进行额外的压力测量。在一个密闭容器内,主要使用…

CDS标准视图:PM通知单 I_LocationAnalysisCube

视图名称:PM通知单 I_LocationAnalysisCube 视图类型:分析 视图代码:点击查看代码 @EndUserText.label: Location Analysis - Cube @VDM.viewType: #COMPOSITE @AbapCatalog.sqlViewName: ILOCANALYSISCUBE @AccessControl.authorizationCheck: #CHECK @ClientHandling.algo…

推荐一款集监控和埋点于一体的前端性能监控工具!开源、简单易用、功能强大!

在互联网的快速发展下,网站已成为企业和个人展示信息、提供服务的重要平台。然而,随之而来的网站性能问题也日益凸显,如加载速度慢、频繁出错、服务器故障、数据异常、网络攻击等。如何确保用户能够快速稳定地访问网站成为了一个亟待解决的问题。 为了帮助大家解决这一问题,…

关关难——软工个人总结

一、学期回顾 1.1回顾你对软件工程课程的想象软工的印象 在课程开始前,我想象中的软工课程是通过理论知识来引导我们学习如何开发一款软件,整个学习的重点是软件如何开发,需要怎样的技术来支撑开发,而课程更多的会教授学生这些技术,事实证明我想错了,软件工程这门课介绍…

设计一个包含KV操作、 磨损均衡的FLASH数据存储组件

在嵌入式环境中常用的存储器有NORFlash、NANDFlash、EEPROM,前两个一般擦写寿命约为10w次,EEPROM的使用次数约为100w次,寿命长的我先不管QAQ,这里的寿命指的是当flash中的存储单元写入或者擦除超过这个次数,这个存储单元可能会出现出错、变慢等无法正常读写的问题。按照木…

cursor 1秒钟写的登录页面,真好看

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>炫酷登录页面</title><style>* {…

nuxt 添加 redis 缓存

这个文章的主要目的是通过 redis 缓存 nuxt2 中服务端渲染的页面。从而优化加载速度以及减轻服务端的压力。Nuxt 是什么 Nuxt.js 是一个基于 Vue.js 的开源框架,旨在为开发者提供一个简单的方式来构建高性能的 Vue 应用。它提供了许多功能,使得开发服务器端渲染(SSR)、静态…

自定义开关(switch)

演示代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>custom_switch</title><…