P3245 [HNOI2016]大数
考虑如何提取区间 \([l,r]\) 组成的数。
设 \(SA_i\) 表示 \(S[i,n]\) 组成的数值,则 \([l,r]\) 组成的数为 \(SU_{l,r}=\frac{SA_l-SA_{r+1}}{10^{n-r}}\) 且统计 \(SU_{l,r}\mod P=0\)。
当 \(10^{n-r}\mod P!=0\) 时:
维护 \(SA_i\mod P\) 莫队求区间有多少个相同即可。
当 \(10^{n-r}\mod P==0\) 时,\(P\in\{2,5\}\)。运用 \(2,5\) 倍数特征即可。
P4688 [Ynoi2016] 掉进兔子洞
不好维护。
发现使用 bitset 可以维护。
bitset 共 \(n\) 位,每个值分配 \(n\),按顺序分布在 bitset 上,每个分配长度等于该值出现的个数。
如 \([1,2,2,3,3,4]\) 分配为 \([1,2,2,3,3,4]\);\([1,5,1,5,1,5]\) 分配为 \([1,1,1,5,5,5]\)。
然后考虑莫队维护。
加入一个数,设当前维护区间共有 \(x\) 个相同的数,该值分配起点为 \(l\),则 bitset 第 \(l+x\) 设为 \(1\)。
删除一个数,设不包括当前删除数当前维护区间共有 \(x\) 个相同的数,该值分配起点为 \(l\),则 bitset 第 \(l+x\) 设为 \(0\)。
这样做有什么用?
因为我们要删除公共部分,即三个区间每个数出现次数的最小值。这样做若三个区间对应的 bitset 内位置 \(i\) 都为 \(1\),那么这个数是要被删除的。否则该位就会保留。就是一个类似俄罗斯方块的思想。
我们把三个区间对应的 bitset 分别求出来,做按位与,我们就知道有多少个数被删除了。由于是三个区间同时删除,我们还需要把这个数乘三。最后答案就是总区间长度减去删除数个数。
但是你开不下这么大的 bitset。
开不下只是因为莫队离线,所以我们要同时存三倍的 bitset。所以我们可以通过减少每次存储个数。
把询问分成若干次经行莫队,每 \(34000\) 次询问跑一遍莫队,求出这 \(34000\) 次的答案。清空掉然后处理下 \(34000\) 次询问。
这样 bitset 只要开 \(34000\) 了,开得下。
P8511 [Ynoi Easy Round 2021] TEST_68
子树外范围比较大,不好维护。
看样例发现大部分答案都是所有数中异或和最大了两个数的异或和。
从此考虑,发现假如两个数都在该子树外,则答案为其异或和。而子树中包含两个数中任意一个的数必然是其中一个的祖先。所以特殊的只有两条链。
如何处理?显然使用 01trie。发现从下往上是删除,不会,但是从上往下就是插入。均摊下来就是 \(O(n)\)。
基本的 01trie 求异或最大即可。
细节有点多。
CF1017G The Tree
转化题意。
修改很难处理,询问很好处理,考虑摊一下。
一个点的黑白情况只与他到根的链有关,而获取这些信息可以用线段树加树链剖分实现。所以思考如何把染色体现为线段树可维护的东西。
把过程看作能量传递。每次操作一,相当于为当前点增加一能量,能量每向下传递一个就会减少一。体现增加能量,我们每次操作把对应点能量值增加一;最妙的一点,体现减少,每个点初值为 \(-1\),这样向下求和,为负数就是能量用完了。
此时我们把很多信息集中在一起,他们会互相干扰。而我们要求的是最大可能的能量值,即前缀最大值,是不会被干扰的。
最终统计最大值是否大于 \(0\) 即可。
操作二需要让下面全部变白,即子树恢复 \(-1\) 的初值,且要消耗上面所有能量,则在子树根处增加减少值为最大前缀和。这样就达到了全部清空。
P4979 矿洞:坍塌
全部相同,考虑哈希。
比较经典的,为每个字母随一个哈希值。
判一个区间是否全部相同,首先取得区间任意数的哈希值,然后求该区间和是否与哈希值乘长度相等即可。
修改也是直接修改哈希值。
前后是否相同直接比较即可。
用线段树维护。
P4587 [FJOI2016] 神秘数
区间 MEX。
先想暴力。
排序。假设当前表示 \([1,x]\),多了一个数 \(a\),则强制用 \(a\) 就可以表示 \([a,x+a]\),分类讨论。
\(x+1<a\) 并区间不包含 \(x+1\),则答案为 \(x+1\)。
$x+1>=a 并区间都包含了,变为 \([1,x+a]\) 继续讨论。
但是这样太慢了,考虑数据结构优化。
把上述优化一下,假设当前表示 \([1,x]\),区间内值域 \([1,x]\) 设其和为 \(a\),若 \(a>x\),说明还有数没有用来更新,就可以继续更新,否则都用来更新了,结束。
区间值域和是主席树经典操作,维护,复杂度 \(O(m\log n \log \sum a)\),卡卡常差不多能过。
CF1381D The Majestic Brown Tree Snake
走路题。
核心目标为掉头,考虑什么时候可以掉头。
链是不可以掉头的,而再多一个度,大于两个度的点,如果存在三边长度都大于蛇,那么蛇就可以两次倒车完成掉头。容易发现这是蛇掉头的充要条件。
那么我们找到这些点,只需要判断蛇是否能触碰到就可以了。
首先有点在蛇子树内的可以直接特判掉。然后就是蛇要向上走,那么需要一个地方让蛇头成为蛇尾祖先。贪心的想,把蛇尾调到能走到的深度最大的点,这样是最可能满足条件的,如果蛇可以向上走了,那么它的蛇头或蛇尾就可以触碰到其他任何点,否则就怎么也出不去。
难度在代码实现,思路清晰还是比较简单的。
CF1516D Cut
什么时候会有 \(LCM=Mul\),显然如果一个区间的数都是互质的,他的 \(LCM=Mul\)。
考虑证明,知道 \(LCM\) 的求法是取每个质因数指数最大值,而如果两个数含有同一个质因数,指数小的就会被吞掉,就会比积小。
枚举质因数,处理每个数前后第一个不互质的数。这样枚举左端点,线段树上二分就能求出两两互质的最大右端点。这样相当于有一个跳指针的数组。再预处理一个点向后跳 \(2^i\) 次方的位置,询问就可以直接倍增了。
ARC136E Non-coprime DAG
首先选 \(1\) 不影响答案。
反链这个东西涉及连通性,所以从生成的图的连通性来考虑。
不互质条件也不好用,但是如果比较聪明或者打了表就会发现重要条件:偶数不互质,也就是说偶数只能选一个。
思考如何处理奇数联通性。容易发现一个奇数能走到的最小的点和被走到的最大的点是偶数点。这个点是这个奇数加减最小因数,又因为是奇数所以最小因数是奇数,自然有两奇相加减得偶数。
这个条件是很强的,我们可以把一个奇数点直接挂到其他偶数点上。也就是说判断小于它的数是否能到只需要判断那个数是否能到向前挂的偶数点即可,大于反之。
解决连通性后问题就在求反链了。
容易想到枚举只选一个的偶数,这样在后面的奇数必须挂在该点前面,前面的要挂在后面,使用树状数组优化计数即可。
还可能不选偶数,显然只是把上述条件中挂在前面变成允许挂在该点上,因为这样就相当于没有选这个偶数。