NOIP2017 逛公园
k 等于0就是最短路计数,可以拿
30
p
t
s
30pts
30pts
注意到题目提示我们有0边的情况,如果有0环,且 0 环在1 – n 的某一条长度不超过
d
+
k
d+k
d+k 的道路上,那么条数一定有无限条
于是用
t
a
r
j
a
n
tarjan
tarjan 缩出 0 边的强连通分量,从起点和终点正着倒着跑一遍最短路
枚举 0 边,通过两边的距离判断
考虑先求出最短路,然后
d
p
dp
dp出
f
i
,
j
f_{i,j}
fi,j表示到
i
i
i,比最短路多
j
j
j的方案数
转移:
f
i
,
j
=
∑
f
t
,
j
+
d
i
s
[
i
]
−
d
i
s
[
t
]
−
w
[
i
]
f_{i,j} =\sum f_{t,j+dis[i]-dis[t]-w[i]}
fi,j=∑ft,j+dis[i]−dis[t]−w[i], 可以记忆化搜索
a
n
s
=
∑
i
=
0
k
f
n
,
i
ans=\sum_{i=0}^k f_{n,i}
ans=∑i=0kfn,i
NOIP2017 宝藏
考虑状压
d
p
dp
dp,由于最后选出来的是一棵树,我们可以一层层考虑
f
s
,
i
f_{s,i}
fs,i表示在第
i
i
i层,选了的集合为
s
s
s的最小代价
枚举下一层选哪些,也就是下一层的集合
f
s
∣
s
′
,
i
+
1
=
f
s
,
i
+
v
a
l
s
,
s
′
∗
i
f_{s|s',i+1}=f_{s,i}+val_{s,s'}*i
fs∣s′,i+1=fs,i+vals,s′∗i
v
a
l
s
,
s
′
val_{s,s'}
vals,s′表示从 s 走到 s’ 的最小价值,先处理点到集合的最短路径,再处理集合到集合的,可以
4
n
4^n
4n预处理
复杂度
O
(
4
n
+
n
2
∗
3
n
)
O(4^n+n^2*3^n)
O(4n+n2∗3n)
NOIP2017 列队
我们可以将拿出来的点在线段树打一个标记,这样查询第 x 个就可以在线段树上面二分
最后一列单独开一棵线段树,取出来的点不用一个 vector 存在后面就可以了,线段树用动态开点
NOIP2016 天天爱跑步
将向上向下走的取分开
对于向上走的,如果
d
e
p
s
t
=
d
e
p
u
+
w
u
dep_st=dep_u+w_u
depst=depu+wu,那么会被看见
那是不是就查一下子树
d
e
p
=
d
e
p
u
+
w
u
dep = dep_u+w_u
dep=depu+wu的点的个数呢?
不,我们发现万一在
l
c
a
lca
lca处拐下去了呢,于是需要查分一下,在
f
a
[
l
c
a
]
fa[lca]
fa[lca]处打一个标记
对于向下走的,如果
l
e
n
−
d
e
p
e
d
=
w
u
−
d
e
p
u
len-dep_{ed}=w_u-dep_u
len−deped=wu−depu, 那么会被看见,同样查分一下
然后我们发现
l
c
a
lca
lca会被算2次,于是向下的标记打到
l
c
a
lca
lca上
每个dep开一棵线段树,然后动态开点,第二种情况数组需要平移一下
NOIP2016 换教室
比较裸的概率
d
p
dp
dp,加一维换不换就可以解决了,然后预处理直接
f
l
o
y
e
d
floyed
floyed
NOIP2016 飞扬的小鸟
预处理经过 2 只或2只以上的鸟的解析式,以及每个解析式打到的鸟的集合
g
[
i
]
g[i]
g[i],剩下的没有统计的只有一个人一个解析式
然后状压,
f
s
∣
g
[
i
]
=
f
s
+
1
f_{s|g[i]}=f_s+1
fs∣g[i]=fs+1
NOIP2016 蚯蚓
巧妙得注意到蚯蚓长度的单调性,就是先被切掉的两段,还是比后切掉的两段长
于是开 3 个队列,每次比对头,就可以避免优先队列的
l
o
g
log
log 了
NOIP2015 子串
f
i
,
j
,
k
,
0
/
1
f_{i,j,k,0/1}
fi,j,k,0/1表示到 i,匹配到 j ,匹配了 k 段,当前有没有匹配
转移时看能不能匹配,能匹配的话选不选,第 1 维需要滚动一下
NOIP2015 运输计划
二分答案,然后只考虑
d
i
s
>
m
i
d
dis>mid
dis>mid的路径,考虑如何 check
我们必须找一条边出现在所有
d
i
s
>
m
i
d
dis >mid
dis>mid 的路径中,树上差分一下dfs一遍就知道有没有这样的路径
如果有,我们选一个最大的,看一下减了过后有没有
m
i
d
mid
mid大就可以了
[NOIP2015] 斗地主
贪心+搜索,口胡一下搜索顺序
首先应该先把出的牌多的给搜了,顺子,连对,飞机,然后四带二对,四带二,炸弹,三带1,三带2
最后贪心出对子,贪心王炸即可
NOIP 2014 解方程
做这种题就是要胆大,如果取模后结果为0,那么很大概率它就是为 0
解法也更是暴力,直接枚举
[
1
,
m
]
[1,m]
[1,m]的数,然后代进去看结果,代的时候用秦九韶算法可以
O
(
n
)
O(n)
O(n)
NOIP2014 飞扬的小鸟
f
i
,
j
f_{i,j}
fi,j表示到
(
i
,
j
)
(i,j)
(i,j) 的最小步数
f
i
,
j
=
m
i
n
(
f
i
−
1
,
j
+
y
,
f
i
−
1
,
j
−
x
,
f
i
,
j
−
x
)
f_{i,j}=min(f_{i-1,j+y},f_{i-1,j-x},f_{i,j-x})
fi,j=min(fi−1,j+y,fi−1,j−x,fi,j−x)
如果碰到了管子,就赋值成
i
n
f
inf
inf,然后需要特判在天花板卡不死掉不下来的情况
复杂度
O
(
n
∗
m
)
O(n*m)
O(n∗m)
NOIP2013 花匠
比较巧妙的一道
d
p
dp
dp
是A是B不重要,只要是波浪就行了,于是用
f
i
,
g
i
f_i,g_i
fi,gi记录到i是下降还是上升的最大长度
f
i
=
g
i
−
1
+
1
(
a
i
<
a
i
−
1
)
f_i=g_{i-1}+1(a_i<a_{i-1})
fi=gi−1+1(ai<ai−1)
e
l
s
e
:
f
i
=
f
i
−
1
else:f_i=f_{i-1}
else:fi=fi−1,g 同理
NOIP2013 华容道 好题,单独写 传送门
NOIP2012 疫情控制
二分答案,然后尽量往上跳
开始想的是全部跳到根,但这么一来上去又下来不就走冤枉路了吗
于是有种比较简单的做法是,我们记录一个点很多路径的剩下长度最小的那个拿给我们回退,显然拿最小的来满足自己是最优的
于是把不能覆盖的儿子从大到小排序,将剩余的边从大到小排序,双指针扫一下
如果扫到一个点,从这个点上去过,我们就回退,把大边权留给后面
NOIP2012 开车旅行
很妙很
N
i
c
e
Nice
Nice 的倍增
直接预处理 A,B 从
i
i
i开
2
j
2^j
2j步走到的点以及经过的路径长度
f
i
,
j
f_{i,j}
fi,j
然后就是考察对
s
e
t
set
set 边界的把控能力了
NOIP2011 观光公交
第一反应
d
p
dp
dp…
先转换一些题意,要求最小化
∑
e
d
i
−
s
t
i
=
∑
e
d
i
−
∑
s
t
i
\sum ed_i-st_i=\sum ed_i-\sum st_i
∑edi−sti=∑edi−∑sti
记
T
i
T_i
Ti 为到达时间,
m
x
i
mx_i
mxi 为最大的出发时间
记在
i
i
i 下车的个数是
c
i
c_i
ci,即最小化
∑
c
i
∗
T
i
\sum c_i*T_i
∑ci∗Ti
考虑到如果
T
i
≤
m
x
i
T_i\le mx_i
Ti≤mxi 在这之前的加速对后面是没有影响的
可以对前后分开考虑
考虑到一次修改最多就能修改到将后面的某一个
T
i
T_i
Ti正好为
m
x
i
mx_i
mxi,在这之后后面的贡献就不会被算了
一次修改的贡献为
∑
c
i
\sum c_i
∑ci,而最大次数为
m
i
n
(
T
i
−
m
x
i
)
min(T_i-mx_i)
min(Ti−mxi)
类似超级钢琴,贪心+堆来维护,将四元组
[
1
,
n
,
m
i
n
(
T
i
−
m
x
i
)
,
∑
c
i
]
[1,n,min(T_i-mx_i),\sum c_i]
[1,n,min(Ti−mxi),∑ci] 放进堆,按
∑
c
i
\sum c_i
∑ci 排序
然后取出来后,将区间的
T
i
T_i
Ti 全部减去一个数,从断点左右递归处理再插入堆
复杂度理论上是
O
(
k
l
o
g
k
∗
n
)
O(klogk*n)
O(klogk∗n),但由于每次都找到一个中间的断点,然后两边递归处理,所以区间的总个数不会太多,而且分到后面区间就会比较小
不错的一道题,
∑
e
d
i
−
s
t
i
=
∑
e
d
i
−
∑
s
t
i
\sum ed_i-st_i=\sum ed_i-\sum st_i
∑edi−sti=∑edi−∑sti 的转换极大减小了我们的讨论量
堆 + 贪心的思想也比较常见