Vjudge练习21总结
作者:互联网
written on 2022-06-21
\(A\) 题大家都过了,这题的思路指引还是很明显的,只要确定 \(A\) 中的一个元素,那么其他所有的元素都可以确定,并且随某一元素的变化,总的变化是有规律摆动的。
虽然思路很简单,但是一开始还是写挂了很久,主要的原因在于一种方法超时后没有积极地调整思路,其实这里的思路调整还是很简单的,只要用 \(\texttt{map}\) 记录下所有的差值即可。以后吸取教训,简单题的话,有了正确的思路但是方法不恰当的话,就要及时地积极地调整。
\(B\) 题很有价值,乍一看是一道数据结构题,但是用一般的线段树什么的好像不太好写。这题就当这一类题的典例,写一下此类题的套路好了。
主要思想:将原序列长度为 \(n\) 的数组划分成若干个连续的小区间,每一个连续的小区间内所存的某一元素是相同的。类似于分块的思想吧(当然不是数论分块),将一个块的信息统一处理以保证时间复杂度。一般用 \(\texttt{set}\) 存储主要的信息。
对于这道题而言,\(\texttt{set}\) 记录区间左端点 \(l\),区间右端点 \(r\),以及最后一次操作的时间 \(t\),每一次查询中,一个小区间的贡献值就是 \((T-t)\times \sum_{i=l}^{r} i\),然后,每一次操作,删除与询问的 \(L,R\)有交集的所有区间,并在最左端和最右端分别补上。然后再插入一个时间为 \(T\) 的集合 \(\left[ l,r \right]\)即可。
每次最多增加两个区间,因此可以保证时间复杂度。
还有就是关于 \(\texttt{set}\) 的一些操作,总结如下:
-
使用 \(\texttt{erase}\) 删除元素后,迭代器会直接失效。
-
如果想要循环删除 \(\texttt{set}\) 内的元素,可以用这样的方式:
for(set<int>::iterator it=s.begin();it!=s.end();) s.erase(it++);
- 迭代器赋值赋的是地址,因此某一个地址的迭代器被修改,指向该地址的所有迭代器都将被修改。
另外是一点注意,除法的取模是乘以其模意义下的逆元!
先看 \(D\) 题。
题意:对于一个给定的数列,找出满足 \(\sum _{i=l}^r (a_i-\max(a_i)) \mod k =0\) 的数对 \(<l,r>\) 的个数。
这种题目要么枚举左/右端点,要么枚举最大值,这里采用的方法是后者。步骤:
-
用单调栈线性预处理出其可以作为最大值的符合区间。
-
记 \(s\) 为原数列前缀和,那么题意可转化为 \(s_r-s_{l-1} \mod k =a_i \mod k\)。
-
(启发)用 \(\texttt{vector}\) 存下每一个 \(s\mod k\) 的位置,然后用二分找出某区间内符合的另一半的个数。这也就是对于给定一个区间,求出该区间内等于某数的所有数的个数的带 \(\log\) 解法,虽然效率略低但容易实现。
-
因为有两边,枚举短的那一边,然后用3算出另一边的符合的情况数,据说这样能保证时间复杂度,证明略。
\(C\) 题的关键在于并查集的删边换加边,倒序操作,中间注意每一次的点都是新的,这样能够防止并查集混乱,细节略。
标签:set,21,迭代,Vjudge,练习,区间,元素,texttt,mod 来源: https://www.cnblogs.com/Freshair-qprt/p/16538255.html