记录脑筋急转弯
习惯
链式前向星需要memset head数组
记得特判
20校赛前一天的三角形
https://codeforces.com/contest/1355/problem/C
给三段区间,要求找出能构成三角形的向量的数目。乍一看要画图用线性规划……好麻烦就没写出来,出题人给的是另一种思路:想办法算出对于每个s(a+b<=s<=b+c),有多少对(x,y)的和等于s。这样一来我们就可以枚举z边,然后把当前和大于z的xy取法数目加在答案上。
第一步是个区间加,即对于所有x,把[x+b,x+c]这一段取法值加一,因为是离线的就不用线段树了,在区间首尾打标记然后维护当前点的取法即可,遍历一遍就赋值好了。
1 |
|
最大区间和beta
我们知道单纯求最大区间和可以用dp,在线性时间搞出来。这道题https://codeforces.com/contest/1359/problem/D要求我们求 减去区间最大值后的区间和 的最大值,增加了难度。
首先,我们可以用单调栈求出,对于每个点i,向左向右最远走到哪里可以不遇到比自己大的,这样我们可以确定下来点i可选的有效区间范围(即a[i]在这个范围中是最大值)。接下来我们只需要在这个区间中选择一个包含i的区间,可以用线段树维护前缀和的最大和最小值。在i左侧找到前缀和最小值,在i右侧找前缀和最大值,两者相减就是整体区间的最大值了。相减时还需要排除右边<=左边的情况。
1 |
|
数列翻转一下,再做dp
https://codeforces.com/contest/1366/problem/E
将当前要在a中找到的、每个subarray中的合法最小值称作目标数字。
直接从头开始线性遍历的话会遇到一个问题,就是你无法确定每个subarray中哪个数字是一定要选的,在存在连续一段目标数字的时候。而如果你把ab数组翻转一下,就会发现,遇到的第一个目标数字一定要选,如果不选的话,上一个subarray的最小值就会是它了。
并查集の新体验
https://codeforces.com/contest/1370/problem/E
分析题意得出,要做的就是求去重后的序列能拆分成多少个0101串(或1010),因为这样的串是可以一次处理完。
首先用序列自动机搞出来nxt数组,表示i及之后第一个0(1)元素的位置。然后从前向后贪心地选0101就行,有个问题就是选过的要标记vis,然后如果在找下一个元素时发现选过了,就要沿着nxt一直向下去找,这显然是n平方的。所以我们用了带路径压缩的并查集来处理。fa就表明,当当前元素不可用的时候,下一个要找谁。
https://codeforces.com/contest/1370/submission/84587433
路径压缩
1 | int find(int x){ |