4.23下午
NO.1 来源: GDOI 2014 拯救莫莉斯
分类: 状压DP
简要题解:
- 设 f(i,S,T) ,表示前 i−1 行已经满足要求,第 i−1,i 行的选取状态分别为集合 S,T .
- 令 cover(S)=S∪(S<<1)∪(S>>1) 表示 S 选这个集合中的点能覆盖的点的集合。
f(i,S,T)+cost(i+1,Q)→f(i+1,T,Q) 其中Q∪S∪cover(T)=全集 - 同时记录一下选了多少个点
- 最后答案是 max(f(n+1,S,0))
反思
- 最开始没有看清楚数据范围,后来数组又没开够,有点气。
要及时注意到状态的转移和两行有关,才能定好状态。
4.23下午
NO.2 来源: GDOI 2014 eat
分类: 线段树 离线 区间询问
简要题解:
- 分成左右两种情况思考,询问
(l,r)
也就是
max{ gcd(a[i],a[j]) }
其中 1≤i<l,l≤j≤r 或者 l≤i≤r,r+1≤j≤n - 考虑左边的情况(右边的类似)。询问按照
l
排序,维护以
r 为索引的答案序列 ans[r]=max{a[i],a[r]},i<l 。 - 令
pos(x)
表示
x
这个因数第一次出现的位置,之后如果出现了
a[r] 是 x 的倍数,那么ans[r] 就可以被 x 更新. - 预处理出修改的区间,和询问的区间一起排序,注意
l 相等时询问操作优先。 - 也就是单点修改和区间查询,线段树轻松搞定,时间复杂度 O(n∗D−−√∗logn) 。
反思
- 左右一直想一起处理,没想到应该分开。
- 思路仍然是离线定序枚举其中一个端点,维护关于另一个端点的答案序列。
- > 4.23晚
NO.3 来源:BZOJ 1095 [ZJOI2007]Hide 捉迷藏
分类:动态点分治 可删堆
简要题解:
我做的第一道动态点分治,写一篇单独的题解。
传送门: BZOJ 1095
反思:
- 要把堆表示的什么搞清楚
- 复习一下重心的求法
4.24下午
NO.4 来源: bzoj 4541 [HNOI2016] 矿区
分类: 计算几何 平面图
简要题解:
- 构建平面图
G
的一个对偶图
g , 预处理出每个面的面积 S(x) - 构建的方法很巧妙,把每个点出发的边分别按照极角排序,这样就可以找到每条边
e
的后继
Next(e) 。
找到一条没有标记的边 e ,就顺着Next 遍历直到回到 e ,就可以找到对应一个多边形。设e 这条边所在的多边形(面)为 id(e) , E 为e 的反边,那么在图 g 中id(e)→id(E) ,就有一条边,把这条边定义为为 e 的 关联边,记为r(e) 。 - 在
g
图上随便找一棵生成树
T ,,每个节点预处理子树中的面积和 Sum(x) . - 接下来考虑询问 中的边
e
.设
r(e) 连接 g 中的u→v (对应原图 G 的面)。
如果在T 中 u=fa(v) (正向边)那答案就加上 Sum(v) , 反之如果 v=fa(u) 则减去 Sum(u) . - 正确性? 管他的哦,我*。
反思
- 神题,不解释。
4.24晚
NO.5 来源: BZOJ 2007 [Noi2010]海拔
分类: 平面图网络流
简要题解:
- 题目没有说海拔一定是整数,所以可以取无限接近某个数,换言之,海拔不同的限制没有了。
- 显然海拔
h
满足
0≤h≤1 ,仔细观察发现一定是一片 0 和一片1 组成的。
问题转化为求原图 (1,1) 到 (n+1,n+1) 的最大流。 - 加一条 (1,1)→(n+1,n+1)的边 ,这条边把无穷大的外界分成里外两部分,分别记为 S,T .
- 最大流=最小割=对偶图中 S→T 的最短路。
反思
- 注意原图的边有向的,所以对偶图中的边的方向一定要与之对应,保证满足最小割=最短路的性质。
使用 long long
4.25 上午
NO.6 来源: 【ZJOI2015 Day1】幻想乡战略游戏
分类: 动态点分治
简要题解:
- 对于重心树上的每个节点
x
维护三个值
f(x),g(x),F(x) - f(x)=∑v∈substree(x)d(v)g(x)=∑v∈substree(x)d(v)∗dist(v,x)F(x)=∑v∈substree(x)d(v)∗dist(par(x),v)
只要预处理到上一层重心的距离 fadist 就可以维护这三个值,这样可以 O(logn) 计算某个点的答案。
- 对于询问 考虑移动中心点
x→v
,如果移动后更优,就跳到
v
所在的对应深度的重心树上去继续找,如果移动不了,就说明找到了最优解。这一步的时间复杂度是
O(d∗log(n)) , d 是平均的度数。 - 总时间复杂度
O(n∗logn∗logn∗d)
反思
- 使用 long long !!!!!又多wa了一次。
- 动态点分治最好分成两部分思考:一是构造重心树并且要维护哪些值,二是如何在重心树的帮助下得到最终答案。例如这个题,重心树的作用其实就在于 O(logn) 计算以某点为中心的答案。当然还有可能要用到一些数据结构。
4.25 下午
NO.7 来源: BZOJ 2006 [NOI2010]超级钢琴
分类:贪心 堆 RMQ
简要题解:
- 设三元组
(l,minr,maxr)
表示左端点为
l
,右端点
r 满足 minr≤r≤maxr 的区间。
由于左端点已知,这些区间中和最大的可以用 RMQ 求出,设在 x 处取到最大值。 - 把这样的三元组放进一个大根堆里,每次加上堆顶的值。删除堆顶,
如果minr≤x 那么将 (l,minr,x) 放进堆,如果 x+1≤maxr ,那么将 (l,x+1,maxr) 放进堆,重复 k 次即可。
反思
- 第
k 大这种问题应该一下想到堆。
4.27 晚
NO.8 来源: BZOJ 4771 七彩树
分类:树 DFS序 主席树
简要题解:
- 把每个深度的建成主席树的一个版本,下标是DFS序,值为 cnt[i] ,表示该点是否有贡献。
- 按照深度插入每个点,假设这个点为
x
,那么就要找颜色和
x 相同,并且DFS序最接近 x 的两个点u,v,dfn(u)<dfn(x),dfn(v)>dfn(x) (这可以每种颜色用一个set实现)。 - 考虑树上差分,也就是 [x]+1,[v]−1,[u]−1,[lca(u,v)]+1
- 对于询问 (x,d) ,在 min(n,dep[x]+d) 的 这棵线段树上区间查询 [start(x),end(x)] 就可以啦。
反思
- 可以先考虑一下序列上的情况,再推广到树上。
- 多组数据,注意初始化。
4.28 下午
NO.9 来源:BZOJ 1912 [Apio2010]patrol
分类:树的直径,dp
简要题解:
- 考虑 k=1 的简单情形,记 total=n∗2−2 。给直径端点连上边显然是最优的,只需求出直径的长度 len .那么答案为 total−len+1
- 上述算法的关键是算出了最大的减少量(即直径长度)。假设已经选了直径,那么再选一条路径,如果选了直径上的边,那么总长不但不会减少,反倒会再 +1 。也就是说直径上的第二次对减少量的贡献为 −1 .
- 所以把直径上的边权值改成 −1 ,求出新的直径 len2 ,那么答案为 total−len−len2+2
反思
- 记录 max,secondmax ,注意更新 max ,时也要更新 secondmax 。
- 记录直径路径的方法
4.28 下午
NO.10 来源:BZOJ 3926【ZJOI2015 Day1】诸神眷顾的幻想乡
分类:后缀自动机
简要题解:
- 先考虑一个简单的问题:如何统计一个给定字符串 S 有多少个本质不同的子串?
- 建立
S 的后缀自动机 Ts ,对于一个节点 x ,它表示的设它表示的最长的子串长度为Max(x) ,那么这个节点代表的子串个数为 Max(x)−Max(pre(x)) ,最终答案为∑x∈TsMax(x)−Max(pre(x)) - 这个题也是一样的,从每个叶子节点开始遍历一次整棵树,可以形成一棵Trie。只要对这个Trie建一个后缀自动机,按照上面的方法统计即可。
- 与字符串不同的是,向自动机中插入字符时不是从上一次插入的 last 节点开始讨论,而是从Trie上的父亲节点开始讨论。
反思
- 类比这种方法,后缀自动机的很多东西可以推广到Trie上。