Cover
由包含或相离发现建树,由最优化背包想到维护差分表,由复杂度想到用堆维护
Walker
多个变量的表达式需要观察,如果发现有些是在所有出现中绑定的量,那么直接视作一个一次而不是两个一次相乘
Connect
观察最终连通图的形态:一条链+散块
那么 ( m{DP}) 就可以根据现在到链上哪个点来定义了
本题是某种叫做对着图 ( m{DP}) 的方式的第一题
Equation
构成的方程并不一定需要真的用树剖来精准找环,这样变量这么单一的题目当然可以查分
Rectangle
扫描线的过程中列出贡献形式究竟是什么样子的?
确定矩形的某个边界之后去计算数量可以保证不重不漏
玩游戏
正着做和反着做是完全一致的,那么走到不能走就看看能不能反着走到相应位置
矩形
两个矩形相交等价于矩形的横竖边形成了交错
那么先用 ( m{cdq}) 分治找到有用的矩形,做法是限制矩形中三维偏序求最后一维最值,如果包含则自己是无用的
求出必要矩形后将线段插入线段树维护的 std::multiset
中大力 (
m{dfs})
排列
考虑一种笛卡尔树上的 ( m{DP}) 形式,也就是钦定左子树大小,本题中需要加上两位限制表示是不是靠边和更大的数字
转移需要想清楚再写,本题让我对 “DP转移需要根据实际含义” 一说法的理解
前缀和优化的形式比预料中的要好写许多
最短路
观察最后最优解的形态,一定是 (back o front o back o frontdots o 1)
先求出来两两之间的距离,真的实现 ( m{DP}) 转移的时候用 ( m{SPFA})
本题也被沈子舜同学称作“对着图 ( m{DP}) 的无聊题”
party
想到网络流之后需要降低其复杂度,关注是是否存在一个完备匹配
那么拆开点之后套用 (
m{Hall}) 定理的结论,于是用数据结构维护 std::bitset
即可,判断条件是是否每个集合都有大小不小于自己的邻域
marshland
一种将网格图建成二分图的方式是 ( exttt{上/下}leftrightarrow exttt{左右})
本题直接套用即可,因为不用消圈,所以其余部分非常简单
粉丝
考虑两种计算划分数的 ( m{DP}:)
(f_{i,j}) 表示当前要选择 (i),已经有的和是 (j),另外一种是 (f_{i,j}) 表示划分成 (i) 个数字,总和是 (j) ,后者转移是 (f_{i,j}=f_{i-1,j}+f_{i,j-i})
上述两种做法单独做复杂度都是 (Theta(n^2)) ,但是由其特殊性,在处理 (gesqrt n) 和 (lesqrt n) 的部分都是 (nsqrt n) 的
最后合并即可,在根号分治的加持下,复杂度降至 (Theta(nsqrt n))
卷
乘积如果再想不到取 (log) 真的就白上高中了奥
Huge Counting
考虑组合数奇偶性的判断条件:
(inom {n+m}n) 是奇数当且仅当 (n&m=0) 那么多重集排列的奇偶性的判断条件是 (forall i,jin[1,n] a_i&a_j=0)
证明直接扩展库默尔定理即可,剩下的做法呼之欲出,按维度容斥之后写数位 ( m{DP}) 即可
数树
如果按照集合大小的奇偶性来容斥需要设计一个 (dp[i][j])
表示当前点 (x) 的子树里面选出了 (j) 条非法路径
因为不能转移所以需要添加插头状物,也就是路径末尾朝向上/下/插头已经接上了
鼠树
在 ( m{Segment tree}) 上的叶子也可以表示该点到根的信息,如果有点操作影响范围是自己的子树,表现在线段树上就是一个区间
把一个点的贡献放到控制点上,如果控制点发生改变,将 增量 放到新的控制点上
如果维护每个重链上最浅的控制点,那么查询控制点时先跳链比较链上深浅,如果满足再到 std::set
里面二分,这样做复杂度降至一个 (log)
Miner
有向图求欧拉回路:
st[++top]=x; while(top){
int x=st[top]; bool go=0;
for(reg int i=head[x];i;i=e[i].nxt){
int t=e[i].to; if(!mat[e[i].id]){
st[++top]=e[i].to;
mat[e[i].id]=1;
head[x]=e[i].nxt;
go=1;
break;
}
}
if(!go) res[++num]=st[top--],head[x]=0;
}
骆驼
观察最终遍历的形态:将整个棋盘拆开变成 (M=frac n5) 个 (5 imes 5) 的子问题,并且在解决子问题的过程中设置过渡点来进行不同子问题之间的转移
奇数偶数的 (M) 分开画得到不同的走法,将第一个格的最中间的格子留出来给 (n imes n)
每个子问题都从 ((3,3)) 开始走,为了转移可以有上下左右四种走法走到 ((1,3),(3,1),(3,5),(5,3)) 来跳到下一个的子问题的 ((3,3))
剩下的就是拼起来了
特立独行的图
图上最多有一个三元环,该三元环中有一个二度点,删去该二度点后原图是二分图
考虑原图没有三元环的情况所剩余的二分图,每侧的点按照度数排序之后需要满足小度数点的邻域是大度点的子集
这些操作完全可以使用 (bitset) 实现
如果原图存在三元环的话让非二度点为 (L,-L),中间的点是 (0),同时非二度点需要满足是该侧度数最大的点
这些汉字和题目含义完全契合
NOIP2013华容道
直接爆搜要存整张图,观察一下发现变化的只有空格子位置和当前格子位置
再观察一下交换空格子之后满足空格子和当前格子相邻,那么需要存下来的状态数量是 (Theta(nm)) 的
大力 (bfs) 求一下空格子从当前方向挪到另一个方向的最小步数,每次需要遍历固定一个点的所有状态,复杂度 (Theta(n^2m^2))
每次询问先bfs出来一开始的空格子到初始点四周的最小路径长,再用上面的信息建出来图跑跑spfa就好了
UR17 滑稽树下你和我
首先注意审题:两个人都在叶子上就行,不用满足在同一个叶子
预处理点到边的距离,点和点之间的距离,二分答案
在大力扩展的过程中注意两个人可以同时到相邻的位置,需要同时枚举出边
不优秀的实现不能通过UOJ数据