【省选模拟】2 月
2.8
数列
赛时想到了没有优化空间的 DP,受 CSP-S2019D2T2 影响决定打表找性质,然而并没有想到换状态
设 \(f[i]\) 为 \(i\) 为某段最大值的答案,则有
第二个条件比较烦,仔细思考一下,若 \(\exists j<k<i,a[k]>\max(a[i],a[j])\),那么 \((a[i]-a[j])^{2}<(a[j]-a[k])^{2}+(a[i]-a[k])^{2}+c\),即从 \(j\) 转移到 \(i\) 一定不如先从 \(j\) 转移到 \(k\),再转移到 \(i\) 优,因此这个条件实际上是无用的
通过『不合法转移一定不优』规避掉判断合法性
差量
先进行全局询问得到极差,然后二分出一个最值所在的位置,记为 \(p1\)(询问前缀,判断极差是否改变可知两最值是否都在该前缀中)
排除 \(p1\),询问二进制下第 \(i\) 位为 \(1\) 的下标(记为 \(S_i\)),再加上 \(p1\) 询问,两结果做差即可得到这些数与 \(a_{p1}\) 的差(记为 \(T_i\))。考虑将其一一对应,对于 \(a_i\),\(|a_{i}-a_{p1}|=\cap_{\text{the jth bit of i is 1}}T_{j}\),最终得到了每个数与 \(a_{p1}\) 的差
通过极差可以确定出另一个最值 \(p2\),那么 qry1(p1),qry1(p2)
即可得到 \(a[p1]\) 是最大值还是最小值,然后就能推出 \(a\)
\(n\) 很小因此可以随便实现
二进制分组减少交互次数
差值关系从最值入手(大小关系确定)
2.12
来到 hz 的第一场,状态很差,尽快适应新作息吧
好
区间 DP,赛时不会处理前后拼接
考虑 DP 每个区间删空的答案 \(f[l,r]\)。
- \(l,r\) 不在同一次操作中:\(\max\{f[l,i]+f[i+1,r]\}\)
- \(l,r\) 在同一次操作中:“好”的子串是单峰的,可以依此枚举峰点转移,\(\max\{g[l,i]+h[i,r]+v_{a_{i}-a_{l}+a_{i}-a_{r}+1}\}\)。其中 \(g[l,r],h[l,r]\) 表示将 \([l,r]\) 删至公差为 \(1/-1\) 的等差数列(\(a_{l},a_{r}\) 为首尾)的答案
\(g,h\) 的转移可以枚举上一项的位置,与 \(f\) 同时 DP 即可
“不一定要删完”可以由删空每个区间的答案+一维 DP 解决
色
赛时使用 \(O(q\sqrt{m}\log m)\) 的做法通过,赛后发现可以用分块平衡到 \(O(q\sqrt{m\log m})\)
显然答案是一条边,其次这条边一定在 MST 上,然后图被简化为了树
对于每个父亲,用若干 multiset
保存相同颜色的儿子(按边权升序),再用一个全局 multiset
\(ans\) 保存 每个父亲与每种异色儿子的边权 \(min\)(颜色相同的多个儿子只保存边权 \(\min\))的集合。修改时先改变该点所属其父亲的哪个 multiset
(同时修改 \(ans\)),再根据颜色变化和它的 multiset
修改 \(ans\)。时间复杂度 \(O(q\log n)\)
乐
赛时想把 border 转化成 period 容斥,但做不到不重不漏(比如 \(1,2,1,1\),period \(=3\))
正解就是从 border 考虑,设 \(f[i]\) 为前 \(i\) 个元素的答案,转移枚举最短 border 长度:
其中 \(s[i]=\prod_{j=1}^{i}v_{j}\)
发现了卷积形式,但要求 \(j\le i-j\),于是考虑分治。递归边界处特判掉 \(j=i-j\),然后对于每个区间 \([l,r]\),取 \(j\in[l,mid],i-j\in[mid+1,r]\) 卷积并对区间外做贡献
代码比较有扩展性
void cdq(int l,int r) {
if( l == r ) {
if( l+l <= n/2 ) ckadd(f[l+l],f[l]);
return;
}
int mid = l+r>>1; cdq(l,mid);
// 右半区间内部没有贡献,因此递归左半区间后就算出了 f[l:r]
if( l+mid+1 <= n/2 ) {
poly a = poly(f+l,f+mid+1) * poly(g+mid+1,g+r+1);
For(i,l+mid+1,ii, ii = min(n/2,mid+r)) ckadd(f[i],a[i-l-mid-1]);
}
cdq(mid+1,r);
}
为了优化常数,可以只求出前 \(\frac{n}{2}\) 的 \(f\) 再 \(O(n)\) 计算 \(f[n]\)
最短 border 小于等于长度的一半
2.14
开心消消乐
考虑如何 \(O(n)\) 检验:设 \(f[i,j,k]\) (\(i\equiv0\pmod2\))为前 \(i\) 位后添加加 \(j\) 能否得到 \(k\),转移时判断 \(s_{i-1},s_{i}\) 是否在一次合并中消去即可。可以比较自然的扩展到计数,问题在于合法串的不同消去方式会被重复计数
解决方法是改一下状态:设 \(f[i,j]\) (\(i\) 同上,\(j\) 为 \(4\) 为二进制数)为前 \(i\) 位后添加 \(0/1\) 能否得到 \(0/1\)(其实是个状压),前 \(i\) 个球的所有情况一定唯一对应在一个 \(j\) 中。转移时枚举 \(s_{i-1},s_{i}\) 填什么。预处理 \(2^{4}\times2^{2}\) 种转移即可做到 \(O(2^{4}n)\)。
计数类 DP 要求每种情况唯一地存在于一个 DP 状态中
树上的棋局
暂鸽 upd 3.2:
显然每个棋子为一个子游戏,可以归纳得到每个棋子的 SG 值为其到子树中最远点的距离,由于有换根操作,并不好直接维护
考虑以直径中点为树根(记为 \(rt1\)),那么不论如何换根(记为 \(rt\)),每个点到子树中最远点的距离只有两种可能:
- \(rt\) 在该点到 \(rt1\) 的链上:该点到子树中最远点的距离
- 否则:深度(\(rt1\) 到该点距离)+直径的一半(注意直径为偶数需要特判,若在直径的另一个中点子树中则“直径的一半”下取整,否则为上取整)
树剖后线段树维护这两个权值,由 SG 定理可得每个点上棋子数可以 \(\mod2\),因此修改都是形如“区间中每个点异或上各自的定值”,每个区间维护当前值和异或自己后的值,修改时 swap
即可。
查询时只需要特殊处理类型一的点(利用异或的自逆),仍然要特判直径为偶数
时间复杂度 \(O(n\log^{2}n)\),被卡常的话把两个线段树换成一个即可常数减半
所有直径交于一点(中心),所有点到树上最远点的路径一定经过中心
社会黄油飞
把式子变形一下得到 \(e(V)-|V|lim>-lim\),选一条边就必须选其两端的点,最大权闭合子图模型。直接跑会存在什么都不选的情况,这是不合法的
考虑枚举一个点强制选,注意到从 \(i\) 枚举到 \(i+1\) 的时候仅有两条边的容量发生变化,可以先退掉需要减少容量边的流量再在残量网络上增广。每次退流与重新增广的复杂度上界为 \(O(lim(n+m))\)
外校有老哥写了牛逼贪心,求证明/ hack:初始选所有点,删去度数最小点并更新其余点的度数
遇到奇怪的问题想网络流
考虑把若干个贪心拼起来取最优解
2.16
trash round
昨晚造太晚了,睡了早读+赛时 0.5h。。。然后挂大分了
写暴力/特殊性质也要认真对待
数学题
记第 \(i\) 行的数为 \(a_i\)。求 \((i,j)\) 的答案本质是求 \([1,i),(i,n]\) 这些数构成的线性基能否表示 \(a_{i},a_{i}\oplus2^{j}\)
直接做复杂度 \(O(\frac{nm^{3}}{\omega})\),瓶颈在于 \(a_{i}\oplus2^{j}\),考虑分类讨论将其转化为 \(a_{i},2^{j}\)
- 能表示 \(a_i\):
- 能表示 \(2^{j}\):能表示 \(a_{i}\oplus2^{j}\)
- 不能:不能表示 \(a_{i}\oplus2^{j}\)
- 不能表示 \(a_i\):
- 能表示 \(2^{j}\):不能表示 \(a_{i}\oplus2^{j}\)
- 不能:
- \([1,n]\) 构成的线性基能表示 \(2^j\):\([1,i),(i,n]\) 构成的线性基能表示 \(a_{i}\oplus2^{j}\),加上 \(a_i\) 才能表示 \(2^j\)
- 不能:\([1,i),(i,n]\) 构成的线性基能表示 \(a_{i}\oplus2^{j}\)
问题变为求 \([1,i),(i,n]\) 构成的线性基能否表示 \(a_{i},2^{j}\),\([1,n]\) 构成的线性基能否表示 \(2^j\)
前者可以使用带删除的线性基,消成对角线即可 \(O(m)\) 查询能否表示 \(2^{j}\)。另一种做法是记录 \([1,n]\) 构成的线性基能否&如何表示 \(a_{i},2^{j}\)
构造题
题目给了一堆保证,关键点在于平面图(根据四色定理一定有解),每个点度数 \(\le8\)(\(2k\))
考虑将点按坐标排序,依次染色,每次只需要考虑与 \(u\) 相连且已经染过色的 \(4\) 个点,依次记为 \(p_{0\sim3}\),颜色记为 \(c_{0\sim3}\)。
考虑给 \(u\) 染 \(c_0\),那么需要将 \(p_0\) 的颜色改为 \(c_2\),再将与 \(p_0\) 相邻的 \(c_2\) 颜色改为 \(c_0\cdots\)。一直 BFS 下去,如果 \(p_2\) 也要改,那么不合法,对 \(p_1,p_3\) 进行类似的操作即可(此时一定合法,因此 \(p_0\) 到 \(p_2\) 的路径围住了 \(p_1\),且该路径上的点颜色均为 \(c_0\) 或 \(c_2\))
感觉没图不太好理解,懒得画了
网格图构造题
一个重要性质:如果 \((i,j),(i,j+1)\) 同色,那么 \((i-1,j-1)\sim(i,j+1)\) 这六个格一定是联通的,其余同理。
因此要想把 \((x_{1},y_{1}),(x_{2},y_{2})\) 竖向分开,一定存在 \(j\) 使得 \(ans[i,j]=L\)。注意到一旦有一条竖分割线,那就一定不存在横分割线,即所有的不联通点对都是竖向分开的,这样就把二维问题转化为了一维
转化后的问题为:构造一个 \(0/1\) 序列,两种限制:某区间中全为 \(0\) 或某区间中存在 \(1\)。(\(1\) 代表分割线)
有确定正确的 DP 做法。hz 貌似没人写,这题分类讨论巨多因此不想看外校老哥的代码,遂弃疗贺了 ycx 的代码
考虑直接构造方案然后 check
,必须为 \(0\) 的构造一下(分 \(n,m\) 奇偶性),其余均填 \(1\),每个联通块实际上需要通过分割线来保证联通,因此需要特判 sub3。正确性不明
横向分割线的两种图:
DDDDDDD
UUUUUUU
LRLRLRD
LRLRLRU
DDDDDD
UUUUUU
LRLRLR
这题细节巨多但数据极水,个人认为想到降维就行了,写代码也就图一乐
2.18
进制转换
设 \(a_i\) 为 \(b\) 进制下 \(y\) 的第 \(i\) 位,不难得到 \(a_{m}b^{m}\le y<(a_{m}+1)b^{m}\),按套路根号分治即可得到做到 \(O(40000T\log)\)
正解的关键是 \(a_{i}\le9\),而上面的式子只按 \(a_{m}<b\) 估计了上界,更紧的上界为 \(a_{m}b^{m}+9\dfrac{b^{m}-1}{b-1}\),后面加的数为 \(a_{0\sim m-1}=9\) 的值。对于 \(b\le100\) 枚举 \(b\),否则枚举 \(m,a_{m}\) 即可,复杂度约 \(O(300T\log)\)
遇到困难睡大觉
21 年论文题,鸽了
不过退火可过
張士超你昨天晚上到底把我家鑰匙放在哪了
放钥匙的方案数是经典容斥:枚举若干位置强制放 \(a_{i}+1\),设 \(f[i,j]\) 为前 \(i\) 个地方强制放了 \(j\) 把钥匙的系数,然后对 \(f[M,i]\) 做插板法
考虑带上概率。答案可以表示为找到某些地方的概率 \(\times\) 这些地方放 \(\ge n\) 把钥匙的方案数,可以类似地把概率乘进系数里,DP 状态中再加两维表示找到了 \(k\) 个地方,这 \(k\) 个地方强制放了 \(l\) 把钥匙即可
最后计算方案数可以转化为:\(n_{1}+n_{2}\le10^{9}\) 个元素放到 \(m_{1}+m_{2}\le100\) 个集合中,前 \(m_1\) 个集合至少放 \(n_1\) 个,求方案数。根据第 \(n_1\) 个元素和第 \(m_1\) 个集合的位置关系可以得到两个做法:
枚举前 \(m_1\) 个集合有多少个元素,分别插板相乘
枚举第 \(n_1\) 个元素属于哪个集合,答案为 \(\displaystyle\sum_{i=1}^{m_{1}}{n_{1}+i-1\choose n_{1}}{n_{2}+m_{1}+m_{2}-i\choose n_{2}}\)
给定的 \(d\) 是为了减少 DP 状态的,时间复杂度 \(O(M^{2}(\frac{N}{d})^{2})\),瓶颈在于 DP
利用数据特性来减少 DP 状态
可以先 DP 系数,在乘上对应的值
两个相关变量大小不同阶时枚举小的
2.20
T1 T2 都接近正解,但写挂了,T3 不会暴力,于是爆 \(0\) 了,很难受
货币
问题即为把某种颜色改成另一种,求最小的包含所有颜色的区间
数颜色一般从后继考虑,记每个右端点的最大合法左端点为 \(f[r]\),则有 \(f[r]=\max\{i\mid suf[i]>r\}\)。插入一个元素并更新后继是容易的,可以启发式合并颜色。修改 \(suf[u]\) 的对于 \(f[i]=u\) 的 \(i\) 显然可以 \(O(\log n)\) 线段树二分计算,瓶颈在此。
考虑利用 \(f\) 的单调性。\(f[i]=u\) 的 \(i\) 一定在一段区间 \([l,r]\) 中(可以线段树二分求出),且计算出 \(f[l]=v\) 后一定有 \(f[l\sim suf[v]-1]=v\)(\(suf[u+1\sim v-1]\le l<suf[v]\)),区间修改后接着计算 \(f[suf[v]]\) 即可
时间复杂度考虑每次查询会使区间数增加 \(O(1)\),而对于每个 \(u\),由于修改后 \(f\) 仍单调,区间合并次数为 \(O(1)\),复杂度 \(O(n\log^{2}n)\)
利用好均摊来保证复杂度
比赛
每个人在必胜的情况下才会改,因此 \(x\le i\Rightarrow a_{i}\le i\)。考虑倒推,让 \(i\) 成为 \(i-a_{i}\) 的儿子,\(i\) 能胜(把 \(x\) 改为 \(i\) 后必胜)的条件为 \(i\) 的儿子均不能胜,答案为最小的能胜的点(一定是 \(0\) 或 \(0\) 的儿子)
记 \(f[u]\) 为 \(u\) 是否能胜(\(0\) 为能胜),则有 \(f[u]=1-\prod_{v\in\text{son}(u)}f[v]\),修改 \(a_i\) 会改变连边,LCT 维护 DDP (需要虚儿子信息)即可
实现上可以用 set
维护能胜的 \(0\) 的儿子,link,cut
后 access
到 \(0\),更新该链上 \(0\) 的儿子即可
字符串
先考虑找根。由于 trie 和 fail 上的结点编号是对应的,可以把同时存在的边拎出来,这些边构成 \(a\cdots a,b\cdots b,\cdots\),若一个点的度数超过 \(3\) 那么它就是根。否则一定形成一条链,考虑这条链上的邻居,其代表的字符串应为 \(a\cdots ab\),因此其 fail 要么也是链的邻居,要么是根或代表 \(b\) 的字符串(根的儿子),可能的根只有 \(\le3\) 个,枚举即可(注意特判所有点都在链上的情况)
确定根后了,那么 dfs fail 树,对于一对父子 \(u,v\),一定有 \(u,v\) 在 trie 树中向上的边都相同,不过只需要把 \(u,v\) 与其父亲的连边用并查集合并即可,因为上面的边会在其他时候被合并
然后我遇到了两个问题,求教/kk:
- 如果求 ACAM 判断是否合法,是否有比可持久化数组保存转移更优美的做法
- 如果不求 ACAM(如果 trie 上一点有两条转移边在同一集合则非法,否则合法),如何证明正确性
upd:2 貌似很显然,是我菜了(从 border 长度考虑)
2.21
赞美良心出题人,放过了复杂度较劣的做法
排队
考过的套路,还是没想起来
显然逆序对之间会连边,最大独立集即为 LIS。记 \(f[i]\) 为以 \(i\) 结尾的 LIS 长度,若不存在可能在 LIS 上的点 \(j\) 满足 \(f[j]=f[i]\),那么 \(i\) 一定在 LIS 上。
LIS 是可逆的,记 \(g[i]\) 为以 \(i\) 开头的 LIS 长度,满足 \(f[i]+g[i]-1=LIS\) 的点才可能出现在 LIS 上
路径相关问题可以正逆两个方向同时考虑
麻烦的杂货店
考场做法是离线+根号分治,\(O(n\sqrt{m}\log n)\)
以下是正解。只考虑向左找匹配括号,向右同理。
把左右括号分别记为 \(1,-1\) 并做前缀和 \(s\),记 \(pre[i]=\max_{j<i,s_{j}<s_{i}}\{j\}\),那么 \([pre[i]+2,i]\) 是合法的括号序列,且 \([pre[pre[i]],i]\) 中不存在跨过 \(pre[i]\) 的合法区间(均可以把 \((i,s_{i})\) 画在坐标系上考虑)
对于询问区间 \([ql,qr]\),记 \(l,r\) 为最左、最右的区间最小值位置
分治
容易用线段树二分找到\(l,r\),那么 \([l,r]\) 是合法区间,然后递归 \([ql,l),(r,qr]\) 即可。时间复杂度 \(O(n+m\log^{2}n)\)
倍增
记 \(le[i,j]\) 为从 \(i\) 开始,走 \(2^j\) 次 \(pre\) 到达的点,\(f[i,j]\) 为答案。询问时把 \(ql,qr\) 在保证 \(ql\le qr\) 的前提下同时向中间倍增,最后 \(ql,qr\) 一定到达 \(l-1,r\),把沿途的答案与 \(qr-ql\) 取 \(\max\) 即可。时间复杂度 \(O((n+m)\log n)\)
ST 表
用 ST 表可以求出 \(l,r\),也可以预处理以某区间中点为右端点的答案(最小左端点),然后询问 \((r,qr]\) 即可。由于有 \(s_{r}<s_{qr}\),因此不用担心左端点超出 \(ql\)。时间复杂度 \(O(n\log n+m)\),非常优秀
2.23
签到题
由度数 \(\le3\) 不难得到最小割 \(\le3\),比较困难是 \(=2\) 的部分
考虑一个边双,求出其 dfs 树。最小割 \(=2\) 即为删去两条边将树分成两个等价类,且从这两个等价类中分别任取一点,最小割都是 \(2\),而同一等价类内部点对间最小割为 \(3\)(最小割树理论)。对这两条边分类讨论:
- 树边+非树边:删掉这条树边后树上的两个连通块间仅有一条非树边相连,这条非树边从树边的子树伸上去。树边的子树为一个等价类
- 树边+树边:一定是祖孙关系,且跨过一条树边的非树边都跨过了另一条(否则由于是边双,两边的子树各有一条不同的返祖边伸上去)。两树边之间的连通块为一个等价类
考虑对每条非树边随机一个权值,树边的权值为跨过它的非树边的权值异或。第一种情况为一条树边的权值等于一条非树边的权值,第二种情况为一条树边的权值等于其祖先树边的权值。得到两个连通块后可以给其中一个中的所有点异或上随机权值,最终权值相等的点在同一等价类。使用树上差分+哈希表即可做到 \(O(n)\)
用随机权值异或表达等价关系,注意使用
mt19937_64
来保证正确率
卷王
根据直径相关理论,合法情况一定有 \(|S|\le3\)(两个直径端点和 \(-1\)),分类讨论即可
构造方法为先构造唯一的直径,再在不影响的地方挂菊花来放置多余的点
某些题可能只有特殊情况有解,那就不需要考虑一般情况
注意小数据,可能需要特判
2.25
快放假了,于是准备摸鱼,结果最后若干 min 会了 T3,差 30s 交上去,非常生气
小说
使用 ACAM 可以做到 \(O(\sum|s_{i}|^2)\),但并没有这档分/kk
自选题,鸽了
LJJ的电阻网格
调和级数部分和有近似公式:
其中 \(\gamma\) 为欧拉常数,使用 long double
计算 \(H(10^{9})\) 可以近似到 \(0.5772156649015\)
祖先
考场做法是 \(O(n\sqrt{n}\log n)\) 的根号分治
以下是正解。记 \(s\) 为子树权值和,考虑把答案简单容斥为 \(\displaystyle\frac{s_{u}^{2}-a_{u}^{2}-\sum_{v\in son(u)}s_{v}^{2}}{2}\)
单点加对 \(s\) 的影响是链加,但不好算 \(\sum s_{v}^{2}\)。考虑树链剖分(类似 DDP),维护每个点轻儿子的 \(\sum s_{v}^{2}\),跳轻边时更新,每条重链只需要作区间加、单点查询即可
子树加对祖先的影响类似单点加,对子树内部的影响可以先记录在子树根上,询问时链查询即可得到该子树被加了多少次,额外维护 \(\sum s_{v}siz_{v},\sum siz_{v}^{2}\) 即可做到给所有轻儿子同时子树加后求 \(\sum s_{v}^{2}\)
答案与儿子有关时考虑 DDP 的思想
2.26 (accoders)
排队
题目中计算方式求出的逆序对数为 \(\sum\max(a_{i}-i,0)=\sum\max(i-a_{i},0)\),一定是小于等于真实逆序对数的
考虑何时会算少。对于第 \(i\ (a_{i}>i)\) 个元素,若存在 \(j<i,a_{j}>a_{i}\),那么无法统计 \((j,i)\) 这对。进一步观察发现 \(j\) 也满足 \(a_{j}>j\),因此所有 \(a_{i}>i\) 的元素是递增的。对 \(a_{i}<i\) 的元素也有类似结论。如果确定了 \(a_{i}>i\) 的元素,\(a_{i}\le i\) 的元素也就确定了
只考虑 \(a_{i}>i\) 的元素并忽略给定元素。把 \((i,a_{i})\) 放在坐标系上,这些点的 \(x,y\) 坐标都是不降的,可以看做从 \((0,0)\) 走到 \((n,n)\),不接触直线 \(y=x\) 的方案数(为卡特兰数)。对于题目给定的前 \(m\) 个元素,只需要检查一下合法性,并改变起点即可(从最大的 \(a_{i}>i\) 的点开始走)
联立不等式来观察
如果特殊情况下答案是卡特兰数,那么可以考虑把一般情况往格路计数上转化
烽火戏诸侯
没题解,可能闲下来的时候会去看 AC 代码
总结
成绩比上个月好看一点,可能是心态变好了?不过更可能的原因是题目风格更适合我了,感觉很久没有遇到奇怪的 DP 了
也许是模拟赛打太多了,感觉越来越不重视。考场上摆烂、对挂分无所谓、不补题/贺 std,问题还是蛮多的,下个月开始记录 rk & 得分来解决吧,希望省选带来的紧迫感能起一定作用
出现了写不完代码的情况(虽然只有很少几次),不知道是不是对拍太多了,虽然有大样例不太容易挂分,但缺少对拍辅助调试/心理暗示很不习惯,尝试调整一下