首页 > 其他分享 >P4690 [Ynoi2016] 镜中的昆虫 题解

P4690 [Ynoi2016] 镜中的昆虫 题解

时间:2024-03-01 19:00:23浏览次数:30  
标签:pre 颜色 题解 Ynoi2016 查询 P4690 修改 区间 极长

题目链接:镜中的昆虫

经典题了,我们首先回顾下颜色数的常见做法统计:

对每个位置维护一个 \(pre_i\),表示与当前位置相同的颜色上一次出现位置。那么我们分讨一下。

查询 \([l,r]\) 得到颜色数,对于 \(pre_i<l\) 的 \(i\) 点,显然它就是这个区间内 \(a_i\) 对应颜色出现的第一个位置,我们把它作为贡献点,而其他的 \(pre_i \ge l\),显然意味着,在当前区间内是存在前驱贡献点的,并不需要作为贡献点。所以颜色问题就转化为询问 \(i \in [l,r]\) 上有多少个 \(pre_i<l\)。

本题涉及到了区间覆盖,那么很显然,对于单纯地暴力修改每个 \(pre\) 是不现实的,这里先考虑不带修的区间段问题。

如果有若干段连续颜色段,询问某个段的颜色个数,那么一个考虑不带修,区别于传统的 \(HH的项链\) 问题解决方式,我们是预处理以后跑扫描线去做的,本质也是二维数点:我的某篇讲解文。参照了下题解区的一些大佬和我之前写的这篇文章,我对颜色数又有了新的看法。

对于一个极长连续颜色段,我们可以沿用之前文章中提到的代表元和作用范围的观点,对于一个极长颜色段来说,我们的当前点的作用范围为 \([pre[i],i]\),代表元为 \(color_{first}\)。为什么选第一个点作为代表元贡献,那是因为,对于一个颜色段来说,它的贡献只有 \(1\),而这个贡献可以选自这里面的任意一个元素,我们强制规定第一个点元素进行贡献,方便处理。

我们现在加上带修,看看上面的观点是否正确。对于如果上述的极长颜色连续段 \([l,r]\) 遇上了带修区间 \([L,R]\) 考虑有部分交集,并且二者颜色不同:

  1. \(l<L,R\le r\),这个时候会分为两段,显然前段 \([l,L-1]\) 依旧还是第一个颜色作为代表元,后半段则为 \([L,r]\),\(L\) 作为新一段的代表元,显然是非常容易做到的。

  2. 在 \(1\) 的基础上,\(R<r\),那么就是分为三段,最后两段为 \([L,R]\),最后一段 \([R+1,r]\),显然这三个极长连续段的第一个元素都可以分别作为代表元元素,且非常容易操作。

那么其实关于极长连续段我们就可以抽象为 \((pre[i],i)\) 的贡献,其中 \(i\) 为这个连续段的第一个元素,类似化段为点的思想,不得不说颜色数这个真是经典又永无止境的问题。

那么考虑正儿八经的带修,这玩意在线显然树套树空间好像不是很行,毕竟 \(64mb\) 限制,那么显然考虑离线,离线带修又有二维数点的,那么显然是 \(cdq分治\) 了。

现在考虑构造出修改与查询,查询很简单,对于区间查询,并且颜色数这个问题属于可差性问题,可以转化为前缀和作差:\([0,r]\) 上的颜色数减去 \([0,l-1]\) 上的颜色数。

考虑如何快速修改上述提到的极长连续颜色段,一个比较自然的想法就是分桶,为每个颜色进行分桶,那么我们可以快速知道待修改的颜色段。为了快速定位到 \([l,r]\) 的插入与删除,我们使用平衡树维护每个颜色桶。对于修改 \(pre\) 和传统颜色数问题一样,先去掉原有的 \(pre\) 贡献,再加入新的 \(pre\) 贡献。

  1. 对于某个颜色桶中增加一个 \([l,r]\),我们可以快速基于二分出红色段,考虑 \(last\) 段的开头 \(l\) 修改 \(pre\) 为 \(l\)。而 \(l\) 处的 \(pre\) 应该修改该为蓝色段 \(pre\) 的 \(l\)。

  2. 对于删除,显然只需要考虑 \(last\) 的 \(pre\) 变为了蓝色段的 \(l\)。

当然蓝色段不存在的情况下自然是 \(0\) 了,特判一下。

对于一个 \([l,r]\) 上如何知道需要删除以及增加哪种颜色的连续段,这个玩意 \(ODT\) 就能办到,本题由于 \(ODT\) 只与修改的查询有关,修改只有区间赋值,所以复杂度也是完全正确的。非随机数据下的 \(ODT\) 这种颜色均摊为 \(O(n)\),即最坏的时候就是 \([l,l]\) 的修改。

这里简单提提什么情况下 \(ODT\) 在非随机数据向下会被卡,首先除了区间覆盖操作以外,还有其他的操作,比如区间加操作,那么构造卡的数据很简单,比如区间 \(+\),在初始状态下反复 \([1,n]\) 进行 \(+\),每次修改即为 \(O(n)\)。另一种拥有区间查询询问,由于数据不随机,我们的 \([l,r]\) 可以每次 \([l,l]\) 使得颜色段数无法均摊到 \(\log{n}\),这个时候查询每次 \([1,n]\),那么查询的单次复杂度即为 \(O(n)\),也能卡。本题仅仅用到总均摊数 \(O(n)\) 的结论,所以复杂度完全正确。假如是随机数据,则颜色段数量均摊为 \(O(\log{n})\),注意前者为总均摊,这里说的随机数据为每时每刻均摊。其实也比较好理解,如果我的 \([l,r]\) 够长,那么其实跑出来就跟随机数据差不多了,够短只用到了遍历,最坏也仅仅是趋近于暴力,有根号分治那个思想的味道了。

那么这样一来就可以轻松地处理出修改和查询离线数据,我们的 \(cdq\) 本质是处理偏序问题的,注意到其实还有一个序:\(时间序\),修改和查询的时间不能乱,这种序和数组下标序是差不多的,我们不需要刻意排序,直接按照对应的时间序下放就行。查询的时候,显然是 \(pre \le l-1\) 时,就加入 \(firstPos\) 这个点作为代表元贡献,其实可以看做就是一个带修版的 \(HH的项链\),树状数组查询贡献,注意我们的每个查询要写两部分,写成前缀和作差的形式。在带修的基础上,加入了化段为点的思想,最后注意一些细节,比如离散化,初始化加入初始数组的 \((pre_i,i)\) 贡献。

最后注意到一个问题,对于一个区间覆盖,区间内的新的极长连续段怎么分配,其实对于同一颜色段,我们想怎么分配极长连续段都行,方便 \(ODT\) 的维护,这里给出一种巧妙的分割方式:\([l,r-1]\),\([r,r]\)

标签:pre,颜色,题解,Ynoi2016,查询,P4690,修改,区间,极长
From: https://www.cnblogs.com/Athanasy/p/18042825

相关文章

  • window.open 循环下载多个文件会打开新页签问题解决
     批量下载文件,循环使用window.open(url)的方式会打开新页签,参考了一位大侠的文章,使用iframe可以的:https://blog.csdn.net/nanke_yh/article/details/125145717如下:fileList.forEach(file=>{//同时下载多个文件,使用iframe下载,因为window.open或者a......
  • $\text{20240301}$ 字符串练习题解
    \(\text{20240301}\)字符串练习题解一定要写冬令营的题吗?遗憾的。P9717给了一个\(n\)个数的首尾相接的字符串,求若干个操作后能形成的不同的字符串大小。一次操作定义为:将字符串内所有的\(\text{01}\)同时改成\(\text{10}\),如图。通过这张图我们似乎发现了一个规律,这......
  • CF1937D Pinball 题解
    题目链接:https://codeforces.com/contest/1937/problem/D题意简述一个长为n的格子,用'<'或'>'组成的字符串表示,在位置i放一个小球,当前所在位置是'<'则下一秒左移一步,否则下一秒右移一步。小球移动后,之前位置的符号反转,'<'变成'>','>'变成'<',直到小球离开整个......
  • [CF1804F] Approximate Diameter 题解
    题目链接题目分析显然图结构不太好维护,容易想到维护树结构。维护生成树看起来就不太靠谱,容易想到维护最短路树。keyobservation:我们固定一个端点(不妨为\(1\)),求出这个点到每个点的最短路长度的最大值\(x\)。则一定有\(\lceil{d\over2}\rceil\lex\led\)。证明:显然\(x\l......
  • CF1827C Palindrome Partition 题解
    CF1827CPalindromePartition题解题面题目传送门。称一个字符串是好的,当且仅当它是一个长度为偶数的回文串或由若干长度为偶数的回文串拼接而成。给定一个长度为\(n\)的字符串\(s\),求有多少\(s\)的子串是好的。$1\len\le5\cdot10^5$,\(s\)仅包含小写字母。......
  • P6185 序列 题解
    如果发现自己莫名其妙错了,可能是代码UB,还开O2!!!!!!!!!!!传送门首先,对于每个操作2,将\(u_i,v_i\)连边。连边之后每个连通块内部可以在总和不变的情况下任意改变。用并查集将每个连通块缩点,然后对于每个操作1,将\(u_i,v_i\)连边。得到的图又会分成若干个连通块。判断整个图是否可行,只......
  • [ABC238F] Two Exams 题解
    [ABC238F]TwoExams题解思路解析这题很麻烦,因为有两个维度。所以可以想到先按照第一维排序,这样就不需要考虑第二维的问题。其次再发现数据范围小,可以想到能用dp做,接下来就考虑如何dp。首先我们要知道我们遍历到了第几个公民,同时还要知道还剩下几个代表名额,同时我们还需要思......
  • P8085 [COCI2011-2012#4] KRIPTOGRAM 题解
    P8085[COCI2011-2012#4]KRIPTOGRAM题解本文原发布于2024-02-07洛谷题库P8085[COCI2011-2012#4]KRIPTOGRAM题解区,现于2024-2-29转载至博客园思路解析这道题目的主要难点在于如何判断明文中形如\(\texttt{abcb}\)的子串可以和密文\(\texttt{bcac}\)匹配,因为如果......
  • 个人题解:江苏省选 2019 第二轮
    精准预测我们首先发现每个人每个时刻只有生死,所以我们可以建一个2-sat模型。每个人对应\(T+1\)个节点,表示这个人在每个时刻的生死。那么,题目的条件可以直接在这个模型上面建图,还要注意第\(t\)秒死亡可推出第\(t+1\)秒死亡和第\(t+1\)秒存活能推出第\(t\)秒存活的两......
  • 后端项目打包相关问题解决
    在对项目进行打包后,我运行jar包发现出现下面错误:nomainmanifestattribute,in"app.jar" 在“app.jar”中没有主清单属性说明jar包里面的META-INF/MANIFEST.MF文件中没有Main-Class这个属性于是我解压jar包,到META-INF/MANIFEST.MF文件中手动添加了Main-Class: com.xxx.xx......