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是我见过的有史以来最坑爹的一场考试了. 今年北京市考点有一个是我们学校,我还恰好被分到了自己学校(还是自己天天上课的那个教室),于是我同时报了普及提高 ...
随机推荐
- 【Java EE】Day06 JDBC连接池介绍、C3P0连接池实现、Druid连接池实现、JDBCTemplate
一.数据库连接池介绍 1.引入 之前:每次都要获取连接释放连接 现在:连接重复使用 2.概念: 存放数据库连接的容器 3.实现 DataSource接口 三种实现 标准实现 连接池实现 C3P0 Dr ...
- CSS中和颜色及渐变
CSS可以设置的颜色 颜色名称 transparent(全透明黑色) pink yellowgreen 等指定的颜色名称 16进制 #ABCDEF 参数 含义 范围 AB 红色渠道值 00-FF CD ...
- kernel 启动流程
一.概述 之前学习了uboot的启动流程,现在接着学习uboot的启动流程,关于 kernel 的启动流程分析的大佬也是很多的,这里还是通过流程的图的方式进行记录,为了像我一样的新手,直观的了解 ke ...
- 安装es可视化软件Kibana
一 Kibana介绍 Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 协作. 您.可以使用 Kibana 对 Ela ...
- Python函数/动态参数/关键字参数
1.函数 #函数语法: #函数名规范:小谢字母开头,不同字母下划线隔开(字母数字下划线) #def 函数名(): #函数体:希望函数做的事情 1.1.无参函数 #无参函数 def music(): p ...
- 2022NewStarCTF新生赛一些比较有意思的题目wp
Misc_蚁剑流量分析 Pcap的文件可以直接使用工具 编辑器打开目录,一个一个看,可以找到eval危险函数 看到n3wst4r,直接使用linux正则匹配,找出相关内容 Url解码,了解一下蚁剑流量 ...
- 【转载】EXCEL VBA-区域选择
1- 区域命名 ThisWorkbook.Names.Item("foo").RefersTo =Tabelle1!$A$1:$B$1 ThisWorkbook.Names.Ite ...
- vue中wowjs的使用
笔者亲测,在vue中使用wow.js如果不按照以下方法实施,会出现意想不到的BUG,网页刷新后图片就全部突然看不到了,被增加了一个隐藏属性,建议大家严格按照方法执行,不要随意使用 (1)通过npm安装 ...
- vulnhub靶场之FUNBOX: GAOKAO
准备: 攻击机:虚拟机kali.本机win10. 靶机:Funbox: GaoKao,下载地址:https://download.vulnhub.com/funbox/FunboxGaoKao.ova ...
- .Net6 使用 Ocelot + Consul 看这篇就够了
前言 卯兔敲门,新的一年,祝大家前'兔'似锦!希望大家假后还能找到公司的大门 O(∩_∩)O !书接上文,我们使用了 Consul实现了服务注册与发现,对Consul不熟悉的同学可以先看看.这篇文章我 ...