一些题(一)
[CERC2014] The Imp
一个观察,对于已经确定的宝箱集合,按照 \(b_i\) 升序依次选一定是最优的,证明可以考虑调整。所以按 \(b_i\) 降序排列进行 dp 即可。
https://www.luogu.com.cn/record/59632899
[ICPC2019 WF] Traffic Blights
设 \(m_i=r_i+g_i\),考虑依次计算每个前缀拦下车的概率。
一个简单的想法是枚举到 \(\operatorname{lcm}m_i\) 进行计算。然后发现对于互质的一些部分,由于中国剩余定理,可以分别计算然后合并;对于 \(m_i\mid m_j\), 可以把 \(i\) 并到 \(j\) 上一起计算。那么困难的部分就是既不互质也不整除的情况。
考虑 \(M=2^3\times3^2\times5\times7=2520\),将所有时间按 \(\bmod M\) 分组考虑,这样新的周期就变为了 \(m'_i=m_i/\gcd(m_i,M)\)。发现此时 \(m'_i\) 要么互质要么整除,方便计算,总复杂度为 \(O(Mn\max m_i)\)。
https://www.luogu.com.cn/record/59639555
[ICPC2014 WF] Maze Reduction
一个乱搞做法,随 \(30\) 次,每次随一个足够长的序列表示每走一步后顺时针转多少次,记录下以每个点作为起点,依次经过房间的度数。然后用 hash 判一下两个点每次走出来的度数序列是否相同就好了。需要注意的是一开始的方向不确定,所以要从每个路口都开始一边然后找最小表示之类的来判循环同构。
https://www.luogu.com.cn/record/59719485
[CERC2015] Looping Labyrinth
从原点出发,有三种情况:走不到任何其它矩形的左上角,只能走到一条直线上所有矩形的左上角,或能走到平面上所有矩形的左上角。考虑从原点开始 bfs \(2\times10^6\) 步,边能区分出以上三种情况并预处理出一些合法的点。
回答询问时,考虑找到原点可达的,理询问点最近的矩形左上角。第一、三种情况平凡,第二种情况可以在那条直线上三分。
https://www.luogu.com.cn/record/59808015
[ICPC2016 WF] Spin Doctor
将 \((a_i,b_i)\) 画在平面上,将 \(c_i=1\) 的点染成黑色。那么问题转化为找到一个斜率 \(k\),用两条斜率为 \(k\) 的直线分别从上下夹住所有黑点,使得被同时夹住的白点数最小。
考虑建出黑点的凸包,那么在凸包里的白点一定会贡献答案。对于在凸包外的白点,找到它切凸包的两条切线,那么当 \(k\) 在这两条切线斜率之间时会给答案贡献 \(1\)。于是转化后的问题可以用扫描线解决。
CF1599G Shortest path
当起始点不在那条线上时容易特判,否则,最多不经过一个直线上两相邻点的间隙,枚举它然后分类讨论就行。
https://codeforces.com/contest/1599/submission/131535388
AGC031E Snuke the Phantom Thief
枚举最终偷了 \(k\) 个珠宝,那么横坐标的约束可以给某些第 \(i\) 小的横坐标一个限制,纵坐标同理。于是建出图来跑费用流就好了。
AGC035D Add and Remove
容易想到区间 dp,但是发现左右端点的贡献不一样,所以考虑将它们计入状态。设 \(f_{l,r,x,y}\) 表示删完区间 \((l,r)\) 且 \(l\) 将要贡献 \(x\) 次,\(r\) 将要贡献 \(y\) 次的最小代价。转移时枚举最后一个被删的数,得 \(f_{l,r,x,y}=\min_{l<i<r}\{f_{l,i,x,x+y}+f_{i,r,x+y,y}+(x+y)a_i\}\),答案为 \(f_{1,n,1,1}+a_1+a_n\)。
经过妙妙分析,状态数是 \(O(2^n)\) 的,复杂度为 \(O(n2^n)\)。
https://atcoder.jp/contests/agc035/submissions/26554782
AGC032E Modulo Pairing
发现一定有一种最优方案使得将这些数从小到大排序后所有配对不交,否则可以调整。
有两种配对方式,一种两数之和和 \(<M\),一种 \(\geq M\)。那么可以找到一个 \(x\),使得 \(\leq x\) 的数用第一种方式配对,剩下的用第二种。并且在合法的情况下 \(x\) 越小越好,于是 \(x\) 可以二分。
https://atcoder.jp/contests/agc032/submissions/24239011
AGC037E Reversing and Concatenating
首先答案的开头一定是 \(S\) 中的最小字母,然后发现每次操作可以将开头最小连续段长度翻倍,于是至多只用操作 \(O(\log n)\) 次。每次操作时暴力选字典序最小的串(非最后一次操作时选其反串)即可,复杂度为 \(O(n^2\log n)\)。
https://atcoder.jp/contests/agc037/submissions/26605782
[集训队作业2018] 串串划分
设 \(f_i\) 表示以 \(i\) 结尾的划分个数。转移时考虑容斥,先加上 \(\sum_{j<i}f_j\),然后考虑非法的转移。对于一个以 \(i\) 结尾的极长循环子串,设其循环节长度为 \(x\),次数为 \(p\)。对于不循环的条件,它需要减去 \(\sum_{1<j\leq p}f_{i-jx}\);对于不相同的条件,它需要减去 \(\sum_{1<j\leq p}(-1)^jf_{i-jx}\) ,加起来就是 \(2\sum_{1<j\leq p,2\mid j}f_{i-jx}\)。
由于以 \(i\) 结尾的极长循环子串最多 \(O(\log n)\) 个,并且可以用 runs 直接找到,所以用前缀和优化下转移就可以做到 \(O(n\log n)\)。