完成度
基本完成了,弃坑了
还剩一些太简单的没有打
剩下的都完成了
前言
教练叫我们去把contest hunter的题做完,以巩固基础。。
虽然不是特别想做,但是毕竟基础还是很重要啊,NOIP就是纯粹的考基础啊。我才不会告诉你有些还真的忘了呢
那么就做一下吧。。
由于题数太多,我不想每一题都开新博客了。。
那就全部堆在这里吧。。
可能有些太过简单就不做了,或者在这里口胡一下做法就不打了,这种会写明没写的
如果实在简单的题,可能口胡都不口胡了。。
其实书上应该右详细题解(我没看过),所以应该没什么人看
先把之前写的搬过来
0601 Genius ACM
0807 糖果传递或0502 七夕祭
0805 防线(秦腾与教学评估)
1803 City Game
垂线法直接做就可以了
1801 括号画家
考虑括号序列,多半都是用栈来维护
我们栈维护编号,然后每一次有人加入的时候
统计一下,栈顶编号为a,新压下来是b,那么(a,b)就是合法的序列,更新答案即可
6902 Vani和Cl2捉迷藏
挺好的一个模型啊,这个一定要记住
其实题目就是告诉你,如果选了a,那么b是不能选的
然后有一个结论,那就是答案=最小可重复路径覆盖
当然我们要先对原图做一个传递闭包
为什么呢?
我们考虑,路径条数为
X
X
,答案是
因为每一条路径只能选择一个点,所以可以得到
Y<=X
Y
<=
X
然后,我们只要证明,对于一条路径方案,我们都可以找到若干个点,使得他们符合条件,即可证明
X<=Y
X
<=
Y
,也就是得到
X=Y
X
=
Y
了
设答案集合为
Ans
A
n
s
,一开始就是每一条路径的终点
那么,我们设
Ans
A
n
s
走一条边以后可以到达的点集为E
如果
Ans
A
n
s
和
E
E
无交,那么就符合条件了
否则,我们就拿出交集的点,让他反着他的路径走,如果走到一个点
x′
x
′
,如果这个点不在
E
E
里面就保留下来
我们一定可以找到这样的一个点,因为如果找不到的话,就说明这条路径可以和另外一条路径上连接上,那么路径数–,就和最小可重复路径覆盖矛盾了
时间复杂度是的
6901 骑士放置(没写)
显然,地图是可以黑白染色的
然后就可以得到一个二分图
然后跑n-最小割就是答案了
这里的最小可可以跑网络流也可以跑匈牙利,都是一样的,网络流应该快一些
6802 車的放置(没写)
行和列分别是两排点得到一个二分图
如果某一个点(x,y)可以放,那么就x向y连边
直接跑最大流就可以了
6803 导弹防御塔(没写)
先把n个炮塔,拆成n*m个,表示发射第几次
然后二分一个答案
如果点x在这个时间内可以打到y,就连一条边
然后满流判断就可以了
6402 Freda的传呼机
仙人掌最短路
题解在这里
6401 创世纪
考虑,因为每一个点只连出一条边
因此,每一个点最多属于一个环
于是我们可以直接拓扑一下
入度为0,肯定是不能选的
我们考虑,如果一个点,他是可以选的,也就是已经保证了限制他的点不能选了
我们直接选这个点不会使得答案变差
于是拓扑有两个条件,1.入度为0了 2.他已经可以选了
两个条件满足其一即可
然后最后,会剩下一些点,这些点肯定在环里面,环最多选择n/2个点,然后再遍历一下就好了
6301 疫情控制
很明显,要先二分答案
如果一个人不可以走到1,那么就无脑往上走就好了。。
如果可以的话,就先保留,也可以理解为暂时删除
然后我们可以得到若干个1的儿子是需要有人的去的
并且我们现在手头上有一些可以走到1的点
考虑贪心,就是剩下时间多的走大的点
但是这样的话有一种情况会GG就是这个人走回了自己
这个的话,我们再记录一个每一个儿子,从他那里走上来的,深度最深的是什么
如果我们当前要配对这个儿子的点,剩下时间比从这里走上来的多,那么显然用走上来的是更优的
然后就可以了
6201 走廊泼水节
考虑模拟K算法跑最小生成树的过程
我们先把给定的边排一个序
然后考虑这个边是树边,那么他所在的两个连痛块,就要都两两连出权值为
(z+1)
(
z
+
1
)
的边,就可以了
6101 最优贸易
先来一发强联通缩点
记录一下每一个连痛块最大最小的价格mx和mn
因为这是一个DAG,所以可以拓扑来做
拓扑的时候更新两个东西,一个是
mn
m
n
,一个是
ans
a
n
s
先更新
mn
m
n
,然后
ans
a
n
s
的更新为
mx−mn
m
x
−
m
n
但是要注意一点,并不是所有东西都可以转移
只有1所在的连痛块以及他可以到的连痛块才可以转移
这个也在拓扑排序的时候判一下就好了
时间复杂度是线性的,跑起来似乎比标解要短要快
6202 黑暗城堡
先跑出最短路f
然后如果你就可以给边定向了,当然,是可能没有这条边的
然后剩下的图,我们记一个点的入度为d
那么全部d乘起来就是答案了
4302 Interval GCD
考虑使用更相减损术的扩展
gcd(x,y,z)=gcd(x,y−z,z−y)
g
c
d
(
x
,
y
,
z
)
=
g
c
d
(
x
,
y
−
z
,
z
−
y
)
当然,多个也适用,也就是差分值个第一个数的gcd
然而我并不知道这个
然后就很好做了,先差分一些,就是单点修改了
线段树维护即可
当然第一个数要特别维护,写一个树状数组就好了
4301 Can you answer on these queries III (没写)
经典的线段树
维护一个区间和,维护一个左右的最大段
胡乱合并一下就好了
4701 天使玩偶
显然可以KD-tree或者CDQ分治
CDQ分治则要对四个方向进行讨论,KD-tree直接大暴力就好了
由于对自己的分治能力很有自信,而KD-tree很少写
于是写了KD-tree
KD-tree最近点对是可以卡到
nm
n
m
的,但是一般都不好卡
如果加上替罪羊重构就更难卡了。。
不仅难卡,随机数据表现也十分优秀
在CH上,KD-tree比CDQ分治的快大概3倍左右
4907 作诗
想了一会高级数据结构没有想出来。。
那就用分块暴力吧。。
一开始想的是预处理第
i
i
个块到这个位置的答案
但是会有一个问题,就是零散的位置,我们要知道他的预处理的这一段中出现了多少次,这个我只想到用一个log来搞,调整块的大小后复杂度还是回退化为
O(nnlogn−−−−−√)
O
(
n
n
l
o
g
n
)
于是考虑去掉这个log
我们如果预处理第
i
i
个块到第个块的答案的话,这样我就可以统计每一个数字前
i
i
个块出现了多少次,就可以快速知道这个数字再预处理的这一段里面出现了多少次了
于是就可以把这个log给去掉了
时间复杂度是的
4908 Race
如果用万能的dsu的话,这题由于深度可能很大,需要一个map
复杂度会退化为
nlog2n
n
l
o
g
2
n
显然不是一个优秀的做法
怎么解决深度很大呢?
显然,点分治就好了。只需要维护他到重心的距离,如果大于K的直接毙掉
这样就可以把深度限制在K以内了,开一个桶即可
时间复杂度是
O(nlogn)
O
(
n
l
o
g
n
)
的
4901 关押罪犯
考虑二分答案
那么问题就转化为某些点不可以再一起,问行不行
用一个并查集即可
固定
x
x
和是不一样的,然后随便做做就好了
然后发现,并不需要二分答案,按边权排序,从大到小扫下来就好了
时间复杂度瓶颈在于排序
3201 Hankson的趣味题
n−−√logn
n
l
o
g
n
的做法很显然,枚举因数就好了
然后其实更好的做法也挺显然的。。
就是考虑每一个质因数对答案的贡献,胡乱讨论一下就好了
3301 同余方程
扩展欧几里得模板题。。
复习一下
6B02 升降梯上
直接暴力f[i][j]表示在第I层,手柄在j的最小代价,胡乱转移就好了
3401 石头游戏
还不错的题
容易想到,会出现周期。。
于是我就猜想肯定是某一个位置一直加。然后搞来搞去觉得有点问题。。
然后看了一眼题解
发现思路挺好
用的是矩阵乘法
构造每一步的矩阵和周期矩阵,然后直接做就好了
构造矩阵做这种周期性的题的思想也要学习
3803 扑克牌
很简单的一个题。。
但是智障错误一大堆,调了很久。。
类似的代码复制过去之后居然忘记改了。。调了半天,看来还是尽量不要写成这么恶心的。。
一开始想错了一下,以为大小王一开始暴力枚举当做什么就好了
其实不行,应该是对于不同情况来决策取最小值
思路很简单,记忆化搜索就好了
f[a][b][c][d][e][ff]表示我们还要拿a张第一种,b张2,c张3,d张4,以及大小王分别表示了什么
讨论搜索即可
6B03 GF和猫咪的玩具
考虑两点可以拉紧的最多就是两个点间的最短路。。
跑出最短路,求最大即可
3B16 魔法珠
一个点的SG就是他所有因数种去掉一个剩下的异或和
然后直接
nsqrtn
n
s
q
r
t
n
预处理就好了
3B04 Xiao 9*大战朱最学
同余方程的裸题
用中国剩余定理或者扩展欧几里得解都可以轻松解决
3602 Counting Swaps
容易想到,答案是有若干个不同的环构成的
一个环可以视作为1的位置上是n,2是1..n是n-1
然后环的方案可以DP出来
胡乱分析一下,最优方案肯定是吧他分为两个小环
得到DP:
for (int i=1;i<u;i++)//枚举其中一段被分成什么了
f[u]=f[u]+f[i]*f[u-i]*C(u-2,i-1)*u;
f[u]/=2;
打表发现,其实就是
nn−2
n
n
−
2
然后找出若干个环,随便合并在一起就好了
6B24 Place the Robots
一眼想出网络流
就是你把横着冲突的用一个大点连在一起,然后st连向这个答案
竖着冲突的用一个大点连在一起,然后大点连向ed
得到一个分层的图,然后直接跑最大流就好了
一开始因为网络流建分层图的时候泄露了一句话死循环了。。差点以为方法不优美跑不出来,然后发现4*4都出不来。。找回自信:)
点数和边数都是
nm
n
m
级别的
P老大说他建了很久的图,于是做完就去看了一下题解
发现题解是二分图,他把横着冲突的看做一个点,竖着冲突的看做一个点,然后如果两个点同时属于两个大点,就把大点互相连边,然后直接跑最大匹配就是答案了
6B18 太鼓达人
挺不错的题啊。。
一开始想的是,对于每一个长度为k的01串建点,如果可以到达下一个就连边
于是这样要跑一个哈密顿回路。。
并不可做
其实我们是把长度为k-1的01串看做点,长度为k的01串看做边
其中边的起点是这个01串的前缀,终点是后缀
然后显然这是一个入度和出度都是2的欧拉图,跑欧拉回路即可
6B06 四叶草魔杖
直接装压DP出某些点联通的最小代价
然后装压DP一次吧他分为若干个和为0的块的代价和
第二次DP,就是暴力枚举两个
2n
2
n
来跑
但其实和为0的分配方案很少,初略估计不会超过
2n/2
2
n
/
2
,并且很多状态都不合法,于是还是比较轻易跑过去的
网上有人说可以用网络流做,我差点就信了。。于是最后还是把他hack掉了
6B12 最优高铁环
分数规划+正环判断即可
5102 Mobile Service
f[i][a][b][c]
f
[
i
]
[
a
]
[
b
]
[
c
]
表示第i个指令,人们在a,b,c
可以省去一维,讨论转移即可
5103 传纸条
考虑两个人同时出发
因为都是从(1,1)出发,所以到达同一个点的时间是一样的
所以直接
f[a][b][c][d]
f
[
a
]
[
b
]
[
c
]
[
d
]
表示两人的坐标为这个时的最优解即可
5104 I-country
考虑到按左右两边的轮廓线来看,肯定是会“回来的”,就是左边为
′<′
′
<
′
形,右边为
′>′
′
>
′
形
直接暴力
f[i][l][r][tf][tf1]
f
[
i
]
[
l
]
[
r
]
[
t
f
]
[
t
f
1
]
表示处理到第i行,这一行[l,r]是拿了的,是否已经回来
转移就暴力转移
时间复杂度看起来不行,但实际还是跑得出来的。。
5105 Cookies
显然,按值排序后,每个东西分的糖果是单调下降的
然后刚了很久的贪心刚不出来。。
还是DP吧
f[i][j]
f
[
i
]
[
j
]
表示前i个小朋友,一共拿个j个糖
考虑这种单调下降的形式
所以有两种转移:
1.1~i全部+1
2.在末尾加一段1
5201 数字组合
直接背包即可
5202 自然数拆分Lunatic版
直接背包是
O(n2)
O
(
n
2
)
的
分组背包可以做到
O(nn−−√)
O
(
n
n
)
5301 石子合并
f[i][j]
f
[
i
]
[
j
]
表示i,j这一段的答案
枚举跨度转移即可
可以用四边形不等式优化,但是我学不会
5402 选课 (没写)
直接树形DP即可
5501 环路运输
把序列倍长以后维护一个单调队列即可
5702 Count The Repetitions
我的方法比较暴力。。
不想写了,不好说,大家还是不要学我的方法了吧。。
5A01 任务安排1
比较暴力的是
f[i][j]
f
[
i
]
[
j
]
表示前i个人,分了j段的答案
这个可以用斜率优化优化为
O(n2)
O
(
n
2
)
也可以过(我一开始就写了这个)
但是我们考虑,我们每分一段的时候加上后面s所产生的代价
就可以把第二维的状态去掉了
这样直接做就是
O(n2)
O
(
n
2
)
的了
如果再用斜率优化可以做到
O(n)
O
(
n
)
5E07 划分大理石
考虑每一种大理石,直接做背包可以会
n2
n
2
但是,如果我们把每一种大理石,分成
20,21,22,23.....
2
0
,
2
1
,
2
2
,
2
3
.
.
.
.
.
共log个,因为他们可以构成任意一种方案
于是复杂度就变为
nlogn
n
l
o
g
n
了
5E09 能量项链
倍长一份,然后做一次区间DP就好了
5E01 乌龟棋
f[a][b][c][d]
f
[
a
]
[
b
]
[
c
]
[
d
]
表示每一种卡片剩几张
位置也可以算出来
直接转移即可
5E02 花店橱窗
直接DP就好了
因为要求字典序最小
所以可以从后往前DP,贪心保证前面的最小即可
5E26 扑克牌
思路挺不错的DP
主要是要抓住关键的一点,牌数很少,不超过4张,可以从这里下手
f[a][b][c][d][last]
f
[
a
]
[
b
]
[
c
]
[
d
]
[
l
a
s
t
]
表示还有a种牌剩1张,b种2张。。。。上一张是a,b,c,d中的哪一种
然后暴力枚举转移即可
时间复杂度
134∗4=114244
13
4
∗
4
=
114244
5701 开车旅行
NOIP的题。。写了2h+
那么是不是我前两题要1h拍完才可以啊。。
但是思路很简单,就是写起来细节有点多,写得我头都大了。。
先预处理出每一个点的次近和最近
然后倍增优化一下就好了。。
我的倍增预处理的是这个这个点由A/B开,到下一次由A/B开A/B所走过的路程
询问查询倍增即可
时间复杂度是
O(nlogn)
O
(
n
l
o
g
n
)
的