【noip模拟】Tricks
5月
砍树
把答案写成一个式子,尝试推式子或观察
7~8月
简单的区间
卡常
处理式子:考虑变量和不变量,尝试枚举范围小的变量 & DS统计其他的
在线不好做的考虑离线,不只是多次询问
不好判区间左右端点相等的情况时先不管,最后减
- \(n\) 组询问 \(\sum_{i=l}^r[a_i=x]\),值域与 \(n\) 同阶
在线 \(O(n\log n)\):主席树。
离线 \(O(n)\):将询问区间拆成 \([1,l-1],[1,r]\),按右端点桶排,双指针从前往后扫 \(a\) 和询问,先将 cnt[a[i]]++
,右端点为 \(i\) 的询问答案即为 cnt[x]
。
简单的玄学
先约分后模可以转化成先模后乘 gcd 的逆元
- \(O(\log n)\) 统计 \(n!\) 中 因数 \(k\) 的个数
int cnt = 0;
while( n /= k ) cnt += n;
卡常题 / b
不止可以边拆点,也可以边转点
玄学题 / c
遇到 \(-1\) 的次幂考虑指数何时是奇数
只有完全平方数的约数个数为奇数
影魔
卡常:记录改过的地方,最后改回来,不要 memset
夜莺与玫瑰
- \(O(n^2)\) 预处理 \(\gcd\)
For(i,1,N) gcd[i][0] = gcd[0][i] = i;
For(i,1,N) For(j,1,N) gcd[i][j] = gcd[min(i,j)][max(i,j)%min(i,j)];
影子
不要轻易地放弃一个想法,一定要想清楚为什么不行、能不能改进、能推出什么性质
玫瑰花精
写 DS 前草稿纸上列清楚
调不出 DS 就去洗脸
Star Way To Heaven
某些与点具有相同性质的可以在建图中当作点(比如这题的上下界)
时间机器
有两重限制的可以先化掉一重(排序)在解决另一重(贪心)
炼金术士的疑惑
输入和算法复杂度不同阶时可以 cin>>string
,记得 ios::sync_with_stdio(0);cin.tie(0)
(可以 printf
,只是不能同时 cout
)
老司机的狂欢
一维坐标系上加速度恒定运动的点可以通过判 \((起始位置,结束位置)\) 是否为逆序对来判是否相遇
求字典序最小的方案可以倍增加速比较的过程
Midian
在桶中移动指针求中位数:维护 \(pre\) 表示小于等于当前数有多少个,与桶一起修改,根据 \(pre\) 与 \(mid\) 的大小移动。(\(mid\) 表示中位数是第几大)
Park
对于树上与遍历子树顺序有关的问题可以 vector
存图,reverse
后再跑一边
完全背包问题
把 DP 的状态看作点,转移看作边跑最短路,可以解决一些有后效性的问题
直接跑最短路/高斯消元解决 DP 后效性会 TLE/MLE 时可以分层,层内建图/高消,层与层之间 DP
毛三琛
在一个序列中选一个元素,以此计算答案。shuffle
这个序列后有期望 \(\log n\) 个元素算出的答案比前面元素算出的大(因为最优答案对应元素的期望位置是中点,后一半就没有这样的元素了,前一半同理)
Game
- 给每个数 \(a\) 匹配一个大于它的最小的 \(b\),求最大匹配数
权值线段树,在每次向上合并区间时尝试匹配(对一个 \(a\) 而言,相当与限定与它匹配的 \(b\) 的上限,倍增地扩大上限)
Cover
- 给定一些区间,只有包含和不相交关系,\(O(n)\) 求包含每个区间的最小区间
// l[i],r[i] 存区间的左右端点,按左端点升序,相同则右端点降序
void build(int u) {
while( l[u] <= l[now] && r[now] <= r[u] ) {
fa[now] = u;
build(now++);
}
}
- C++11 中
swap
两个 STL 是 \(O(1)\) 的
Walker
设 \(x_1=x\sin\theta,x_2=x\cos\theta\) 转化为二元一次方程。
Hunter
根据期望的线性性 \(\text E(x+y)=\text E(x)+\text E(y)\) 可以简化对期望的求解
Connect
- 状压 DP 注意预处理来保证复杂度
- 思考哪些状态/转移是等效的来减少 DP 复杂度
矩形
连边后数联通块个数时向一个联通块中不同点连边是等价的
Dove 打扑克
\(\sum x_i=n\Rightarrow|\{x_i\}|\le\sqrt n\)
Cicada 与排序
DP 时如果各位不好一起统计,那就单独算每一位
Cicada 拿衣服
与二进制有关的问题可以从二进制位的数量是 \(\log\) 上考虑
数对
有多重限制时根据等效性/最优性排序去掉一个
c
点分治时询问的一条路径会在两点在点分树上的 LCA 处处理
marshland
网络流技巧:
- 网格图黑白染色,按行分点
- 求流量不超过 \(k\) 的最小费用:跑 \(k\) 次 EK,如果费用为正就结束(裸费用流只能求流量最大情况下的最小费用)
送花
一个序列求区间最优解可以不断右移右端点,开线段树/平衡树动态维护左端点到当前右端点的答案
粉丝/第四题
有多种计算方式,单独的复杂度无法承受,考虑分开算(比如以 \(\sqrt n\) 分开)后拼起来。
第三题
二进制数位 DP 可以类似主席树地找第 \(k\) 大
第四题
通过 \(x^2=\binom x2\times 2+x\) 可以将每种方案中出现次数的平方的和转化为求出现两次的方案数 + 每种方案中出现次数。
Emotional Flutter
看到固定的增量 \(k\) 想模 \(k\) 下同余
Huge Counting
\(\binom nm\) 为奇数的充要条件是 \(n+m\ \text{and}\ m=m\)。
证明:分类讨论 \(\binom{n-1}{m-1},\binom{n-1}m\) 的奇偶,利用 \(n\) 与 \(n-1\) 的最后一个二进制位不同。
打表 购物
大胆猜结论,但一定要拼暴力
状压爆搜时 x = x<<1|1, (x>>=1)&1
比 x |= 1<<i, x&(1<<i)
快,且便于记忆化(位数少)
蛇
观察题目特殊的地方有什么性质
数树
打表找规律
鼠树
相信数据很水
维护一些集合时考虑只维护有代表性的元素,通过它推出其他元素
Sequence
看到 \(10^{18}\) 级别的数据范围不要只想找规律,也可能矩乘
Omeed
线段树维护一次函数:每个结点维护 \(x_r=kx_{l-1}+b\),这样可以通过 \(x_{mid}\) 快速合并
Revive
带修点分治不一定要建点分树,可以只记录每次分治的信息(分治中心,属于哪个子树,求答案需要的东西)
10~12月
T1 出了个大阴间题
通过算偏移量可以缩小值域
T2 最简单辣快来做
看见绝对值想分类讨论
不具可减性的信息可以正反分别前缀和,二维同理
小说
带修的方案存在性问题可以对一个大质数取模(比如回退背包)
骆驼
路径构造方案考虑手模/打表出一个单元,把若干个单元拼起来
回文
如果题目给出暴力实现/伪代码,先思考其本质再优化
混乱邪恶
背包 \(O(n)\) 空间记录方案:
void find(int x) {
if( !x ) return;
ans[pre[x]] = 1, find(x-a[pre[x]]);
}
signed main() {
For(i,1,n) rFor(j,m,a[i]) if( !f[j] && f[j-a[i]] ) f[j] = 1, pre[j] = i;
}
NOIP 2018
不要猜单调性然后三分
可以二分的东西很多,不要钉死在答案上
乘法比大小爆 __int128
时考虑转 long double
除法
卡紧二分边界(精度)
叁仟柒佰万
DP 优化不仅在转移上,还可以去除冗余状态
超级加倍
点分治合并子树复杂度不对时别忘了容斥
树上路径
若干个形如 \((1,1),(x,y)\) 的矩形求面积并:纵坐标的后缀 \(\max\) 之和
法阵
如果 DP 需要知道很多全局信息不妨直接从全局考虑,可能有很多性质
棋盘
统计路径数的题考虑能不能倒过来
如果转移能写成矩乘形式那么就能利用结合律
保险箱
若 \(x\nmid n\),则 \(kx(0\le k<n)\mod n\) 取遍 \([0,n-1]\)
字符串
对于区间 \([l,r]\),前后缀和 \(pre,suf\),\(\min_{l\le i<j\le r}(pre_{i}+suf_{j})=\) 区间和 \(-\) 最大子段和