NOIP2017 - D2T3 - phalanx
按照思维难度加大和代码难度减小的顺序,我们来看这道题的不同做法。
若你无畏,我亦无畏 - 平衡树
平衡树简直是天然用来维护这种操作的——合并两个区间,提取一个值。我们可以对每个行的前 \(m-1\) 位和最后一列各维护一棵平衡树。平衡树上二分得到要删除的数,将当前区间分成 左边 - 要提走的数 - 右边。然后合并左边和右边,在末尾加上会新来的数。
但是这里存在一些问题,也就是我们不能真的给每一行开大小为 \(m-1\) 的平衡树,这怎么办呢?
策略一:动态开点。我们一开始只插入一个大小为 \(m-1\) 的节点代表整个一开始的平衡树,当它的左右儿子存在但是不真正插入。一旦查询到,再把左儿子和右儿子插入进去,再往下遍历。因为我们最多访问 \(q\) 次,所以最多插入 \(O(q\log n)\) 个新点。
策略二:断点分裂。我们在平衡树上维护区间,\([l,r]\) 的区间。同时记录它的大小和原始对应的 \(l\)。当我们查询到要的点是 \([l,r]\) 之间的第 \(x\) 个数时,就返回 \(l+x-1\)。然后删除的时候,将 \([l,r]\) 分裂成 \([l,x-1]\) 和 \([x+1,r]\)。我们发现,每个平衡树其实都是在所有被删除的点的间隔下被分成了若干个连续的区间。每次查询最多分裂出两个区间,点数是 \(O(n)\) 级别的(线性空间)。
策略三:两个 \(Treap\)。我们在前面的过程中,都是实现了 \(n+1\) 棵同功能平衡树。我们想想两棵不同功能平衡树有什么好处——我们可以一个用来记录正常位置被删掉的点,一个用来记录所有新加入的点!那么,我们可以在所有被删除的点上同时维护紧跟着它的一段区间,在”删除 \(Treap\)”上二分找到答案。如果“删除 \(Treap\)”本身已经没有足够多的数了,就在新加入的点里面,也就是“插入 \(Treap\)”里面二分,得到答案。然后每次在“插入/删除 \(Treap\)”上增加一个点,在“插入 \(Treap\)”中增加一个点。
当然,以上的所有平衡树做法中,大部分都使用于所有的平衡树。不过因为是维护区间的缘故,当以 \(fhqTreap\) 为最佳选择。
转圜余地,权衡之策 - 线段树 (Pure)
我们可以使用 \(n+1\) 个动态开点线段树。在节点上记录当前行当前区间没有被删除的数的总数,在叶子节点记录当前点的数。每次在线段树上二分。最多插入 \(O(q\log n)\) 个新点。
在平衡树中存在的问题,在线段树中依然存在。不过因为动态开点线段树的天然性质,解决的方案要更加方便。
策略一:动态权值。对于一个区间,它 \(m-1\) 以内的部分是有先天权值的,以外的部分是没有先天权值的。那么我们在线段树 \(newnode\) 的时候,将新的 \(sum\) 设定成在 \(m-1\) 以内的部分长度。也就是 \(\max\{\min\{r,m-1\}-l+1,0\}\)。这样我们就可以方便的进行二分和加点了。
策略二:两种线段树。我们给每行开两种线段树,一种维护前 \(m-1\) 个数,一种维护新加入的所有数。第一种的先天权值是 \(r-l+1\),只需要支持动态开点删除。第二个负责在新点超出范围的时候查找,不仅删除还要插入。两种不同的先天权值区间用两个不同的线段树来概括,主要代码可以大段复制,只在 \(newnode\) 等为数不多的地方进行更改,免去了维护最后一列和其他长度不一样的烦恼。
策略三:满赋溢出。我们发现,我们其实只需要维护前 \(m-1\) 个有值的位置,而插入其实是从尾部逐步插入。已经被加入的部分本来就应该是 \(1\),后面的部分在二分的时候根本不会被关注到,我们不如直接给所有的区间的先天权值都设为 \(1\)(因为溢出部分的权值对前 \(m-1\) 的查询没有影响)。我们也不需要支持插入了,只需要更改叶子节点的 \(value\) 即可。因为每次修改修改一条链或一个点,还可以使用特殊的方法建树得到更优秀的实现。
思维风暴,人力之伟 - 线段树 \(+\) 其他技巧
策略一:提前处理。我们假设删除点的时候不是删除合并两边,而是保留原来的点。每次处理一行。也就是提前 \(O(n)\) 建出一棵不动态开点的线段树,对于每一行的所有询问,找到它对应原来的位置的哪个点(也就是如果不删除点,只是把点改成 \(0\),它对应 \(m-1+q\) 内第几个点),删掉这个点。整行查询完之后,将所有被删除的位置加回去。预处理对应位置的复杂度是 \(O(q\log n)\) 的。然后模拟部分就不再用到线段树。因为我们已经提前处理出了坐标,所以可以直接利用新的映射关系在 \(Append_x\) 序列中 \(O(1)\) 按照下标查询。至于删除就完全不需要处理了,因为我们维护的就是静态的序列。每次在 \(Append_n\) 里面加一个点即可。
策略二:预后处理。和上面的做法反其道而行之。我们发现,每个询问的答案,要么依赖于前面删除了多少个数,要么依赖于后面加进来什么数。而前面删除了多少个数这种很好处理,对于后面加进来的数,我们可以不去管它加进来什么,而是找到那次修改它它的询问编号。我们对每个询问,处理出它的父亲——也就是它的答案依赖于哪个位置原先的答案。这一过程可以使用线段树,也就是在线段树上二分没有被删掉的位置。如果当前位置的值依赖于 \(append\) 进来的数,就把它的父亲挂上去。否则就是当前行列的答案。最后像并查集压缩路径一样找到每个点的答案。压缩直到当前询问不依赖于别的询问为止。
小技巧:权值处理。我们发现值分两种,一种是原先表中的规律的值,一种是插入进来的新值。原先表中规律的值很好处理,但是新值有点麻烦,需要在线段树的每个点记录。这样就要给每个节点加一个新的信息,增加了规律值的浪费。我们可以用 \(Hash\),对于规律的值,直接按照公式给出答案。否则存进 \(Hash\) 表。每次直接往 \(Hash\) 表里查询,就可以优化一点空间的常数(动态开点,空间很重要)
NOIP2017 - D2T3 - phalanx的更多相关文章
- [luogu P3960] [noip2017 d2t3] 队列
[luogu P3960] [noip2017 d2t3] 队列 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Syl ...
- 【学术篇】NOIP2017 d2t3 列队phalanx splay做法
我可去他的吧.... ==============先胡扯些什么的分割线================== 一道NOIP题我调了一晚上...(其实是因为昨晚没有找到调试的好方法来的说...) 曾经我以 ...
- NOIP2017 D2T3列队
这题我改了三天,考场上部分分暴力拿了50,考完试发现与正解很接近只是没写出来. 对于每一行和最后一列建n+1颗线段树,维护前缀和. 复杂度qlogn 假如你移动一个坐标为(x,y)的人,你要将第x行线 ...
- NOIP2017 D2T3 题解
题面 这种数据范围不是乱搞dfs就是乱搞状压DP 首先应该通过任一方式求出a和b的值: 任意一条抛物线只用两头猪就可以确定,所以我们N^2枚举,并把在这两头猪的抛物线上的猪都存进状态state[i][ ...
- luogu 3960 列队
noip2017 D2T3 列队 某zz选手当时直接放弃了写了50还写错了 题目大意: 有一个n行m列的方阵,第i行j列的点编号为(i-1)m+j 每次把第x行y列的点拿出来,然后把这一行它之后的点都 ...
- 【NOIP题解】NOIP2017 TG D2T3 列队
列队,NOIP2017 TG D2T3. 树状数组经典题. 题目链接:洛谷. 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. ...
- NOIP2017列队(phalanx)解题报告
列队作为NOIP2017最后一道题,其实并不难,只是相对于其它题目,有点小小的工业 首先,这道题我用splay维护的,如果你不会splay,又想学一下splay,可以来这里学一学,接下来步入正题 首先 ...
- [NOIP2017 TG D2T3]列队
题目大意:有一个$n \times m$的方阵,第$i$行第$j$列的人的编号是$(i-1) \times m + j$. 现在有$q$个出列操作,每次让一个人出列,然后让这个人所在行向左看齐,再让最 ...
- [NOIP2017]列队 离线+SBT
[NOIP2017]列队 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵 ...
- noip2017爆炸记——题解&总结&反省(普及组+提高组)
相关链接: noip2018总结 noip2017是我见过的有史以来最坑爹的一场考试了. 今年北京市考点有一个是我们学校,我还恰好被分到了自己学校(还是自己天天上课的那个教室),于是我同时报了普及提高 ...
随机推荐
- WeetCode3 暴力递归->记忆化搜索->动态规划
笔者这里总结的是一种套路,这种套路笔者最先是从左程云的b站视频学习到的 本文进行简单总结 系列文章目录和关于我 一丶动态规划的思想 使用dp数组记录之前状态计算的最佳结果,找出当前状态和之前状态的关系 ...
- 【SQL基础】【记住重命名】高级查询:聚合函数(四舍五入)、分组过滤、排序、
〇.概述 1.功能概述 高级查询:聚合函数(四舍五入).分组过滤.排序. 2.建表语句 drop table if exists user_profile; CREATE TABLE `user_pr ...
- RocketMQ 在网易云音乐的实践
本文作者:蒋星韬,网易云音乐服务端开发工程师. 云音乐线上场景众多,比如直播.评论.广告,各个业务线都会有消息场景比如发奖券,也会有延迟消息和事务消息场景,以及大数据做埋点数据.数据清洗.离线处理等. ...
- 第三模块的下载、requests模块、openpyxl模块
目录 第三方模块的下载安装 下载第三模块的方式 针对下载第三模块时可能会出现的问题 网络爬虫模块之requests模块 自动化办公领域之openpyxl模块 第三方模块的下载安装 第三方模块:别人写的 ...
- SQLMap入门——获取当前网站数据库的用户名称
列出当前网站使用的数据库用户 python sqlmap.py -u http://localhost/sqli-labs-master/Less-1/?id=1 --current-user
- Jmeter之响应数据乱码问题
在进行接口测试时经常长出现响应结果中中文乱码问题 解决以上现象最简洁有效的方法为在测试计划下添加beanshell后置处理器 1.右击测试计划->添加->后置处理器->beanshe ...
- Spring IoC的一些知识点
在日常开发中,接触得比较多的算是Spring生态了,Spring Ioc是Spring Framework重要的组成部分,下面整理了一些Spring Ioc的知识点. 1. 什么是IoC IoC(In ...
- 2022年8月20,第一组,周鹏,从1到m中随机取n个数,n<=m,显示出所有取法
static Random a1 =new Random(); static int m = a1.nextInt(20)+1;//随机取一个1到20的值 static int n = a1.next ...
- prometheus-添加监控linux服务器
1. prometheus-添加监控linux服务器 prometheus添加监控linux服务器 node_exporter:用于监控Linux系统的指标采集器. 常用指标: CPU 内存 硬盘 网 ...
- cs231n学习笔记——lecture6 Training Neural Networks
该博客主要用于个人学习记录,部分内容参考自:[基础]斯坦福cs231n课程视频笔记(三) 训练神经网络.[cs231n笔记]10.神经网络训练技巧(上).CS231n学习笔记-训练神经网络.整理学习之 ...