奇技淫巧的记录
俗话说得好:求上得中,求中得下。虽然说记录下常用的套路不能保证考场上拿100,但可以更有效地骗分。
本文记录学到的任何常用的套路/观察/转化等等。(话说在GDOI的15天前才开这个是否有些迟)
滥用分界线人。标点怪兽。
通过全局构造容易维护的量
比如长剖时继承重儿子,如果要整体加上\(a_u\)就很难维护
考虑把状态换成\(s_v\)也即\(rot\)到\(v\)的权值和即可,注意统计时减去冗余。
一类简单二元加法上界的处理
名字瞎起的
考虑 \(\max_{i,j} [a_i+a_j \le lim](b_i+b_j)\)怎么求。
先变成\(\max_{i,j} [a_i \le c_j](b_i+b_j)\)
只需要对\(a,c\)开值域线段树,记录\(max[a_i=k]b_i\)等即可
可支持插入删除,需配合set
可\(a,c\)值域大,动态开点就行
可做\(mod\)等环形区间问题
loj3273
-
折线的性质观察(如单调性)与维护
-
修改操作的log型集体维护,转化成无修改(如二进制分组保证了折线的单调性,rebuild的运用)
World tour final 2019 C
-
(操作可逆时)寻找中间状态
-
Kummer定理的构造式运用
-
人类智慧:
记 \(f_{n,k} = (\sum_{i \bmod 3 = k}\dbinom{n}{i}) \bmod 2\)
则可归纳证明\(f_{n,0/1/2}\)中总是两个1一个0
Pjudge 21677 染色
-
二分图染色的运用
-
冗余状态的剪枝(\(deg \ge K\)的点数 $ \le $ 边数\(/K\))
CF1750G
-
经典二项式反演
-
问题的转化和简化,对简单枚举的规避
-
秦九昭算法的应用
gym104172I
-
平面分块
-
期望时间复杂度的分析,对点集的shuffle(感觉和最小圆覆盖有点像?)
-
同分治法的点的筛选,保留\(O(1)\)个点
loj6222
-
PN可唯一表示为\(a^2b^3\),其中要求\(\mu^2(b)=1\)
-
经典公式\(\mu^2(i) = \sum_{j^2 \mid i}\mu(j)\),证明考虑分两类讨论,和证明\(\sum_{j|i}\mu(j) = [i=1]\)差不多
-
整除分块的嵌套
双栈模拟deque
先考虑双栈模拟queue:
两个栈记为\(F\),\(G\)。
push时:放到\(F\)里。
pop时:若\(G\)中有元素,pop(\(G\))
否则将\(F\)中的依次pop并放入\(G\),并pop(\(G\))
不难发现这样的顺序正确且每个元素只会操作\(O(1)\)次,总时间复杂度\(O(n)\)
模拟deque时:
前后端插入都简单,分别push进\(F\),\(G\)就行。
有问题的是一个栈空时还要对应方向上删除怎么办。如果暴力把另一个栈的元素全倒过来,可能会反复转移而TLE。
我们充分发挥人类智慧:将另一个栈底下\(\lceil \dfrac {|S|}{2} \rceil\)个元素自顶向下依次pop,并push进\(G\)里,最后pop(\(G\))。具体实现时全部拎出来两边插入即可。
上取整是规避\(|S| = 1\)的case,免得插完了\(G\)还是\(\emptyset\)。这样就不难证明其正确性。
考虑时间复杂度。看上去在\(O(n)\)到\(O(n \log n)\)之间,我们使用势能分析法证明。定义势能函数\(\phi(S)\)(S为整个双栈结构) $ = |S| + ||F|-|G|| $ 。每次push/pop时,如果不触发重构(就是倒一半的操作),只会花费\(O(1)\)的时间,增加\(O(1)\)的势能,相当于\(O(1)\)。触发重构时一个栈为空,有\(\phi(S) = 2|S|\)。而rebuild后\(\phi(S) \le |S| + 1\),\(\Delta \phi \ge |S| - 1\),操作时间复杂度为\(|S|\),可以看做抵消,仅仅耗费了常数的时间。所以总时间复杂度为\(O(n)\)。
回到例题,不过是套了个背包,栈push时更新\(f\),pop时指针下移即可。合并背包求区间max可以滑动窗口。\(O(nm)\)
开ST表的常数优化
记得带log那一维开在前面,n那一维开在后面!!!!
原理:内存连续访问会更快
关于计数
如果问的是最后有多少个满足条件的序列,最好从序列的性质入手,转化成一个充要条件计数,这样不重不漏。
[AGC043C] Giant Graph
- 隐藏的博弈模型:形如一个点转移,它能选当且仅当出边都不选
- 一个边数为\(O(m)\)的DAG,\(SG_i \le O(\sqrt m)\)