其他分享
首页 > 其他分享> > Vjudge练习21总结

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}\) 的一些操作,总结如下:

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>\) 的个数。

这种题目要么枚举左/右端点,要么枚举最大值,这里采用的方法是后者。步骤:

  1. 用单调栈线性预处理出其可以作为最大值的符合区间。

  2. 记 \(s\) 为原数列前缀和,那么题意可转化为 \(s_r-s_{l-1} \mod k =a_i \mod k\)。

  3. 启发)用 \(\texttt{vector}\) 存下每一个 \(s\mod k\) 的位置,然后用二分找出某区间内符合的另一半的个数。这也就是对于给定一个区间,求出该区间内等于某数的所有数的个数的带 \(\log\) 解法,虽然效率略低但容易实现

  4. 因为有两边,枚举短的那一边,然后用3算出另一边的符合的情况数,据说这样能保证时间复杂度,证明略。


\(C\) 题的关键在于并查集的删边换加边,倒序操作,中间注意每一次的点都是新的,这样能够防止并查集混乱,细节略。

标签:set,21,迭代,Vjudge,练习,区间,元素,texttt,mod
来源: https://www.cnblogs.com/Freshair-qprt/p/16538255.html