原来我不只是不会数学和数据结构,连图论和DP也8会 = =
1002 Blow up the city
题意
给出一张
n
(
n
≤
1
0
5
)
n\ (n\le10^5)
n (n≤105)个点的有向无环图(不一定连通),每个出度为
0
0
0的点可视为一个指挥部。
现在有
q
(
q
≤
1
0
5
)
q\ (q\le10^5)
q (q≤105)次询问,每次询问会指定两个点作为补给站。若摧毁一个点之后,任意一个补给站无法到达任何指挥部,那么这算做一个成功的方案,每次询问需要求出有多少种成功的方案。
题解
支配树,所有边取反,再设置一个超级源点向原图中每个指挥部连边,超级源点作为支配树起点。
对于两个补给站,求出LCA去重。
不会支配树,挂起来等补题。
1004 Distribution of books
题意
给出一个长为
n
(
n
≤
1
0
5
)
n\ (n\le10^5)
n (n≤105)的数列,每个数字
a
i
a_i
ai满足
−
1
0
9
≤
a
i
≤
1
0
9
-10^9\le a_i\le10^9
−109≤ai≤109。
可以舍弃末尾任意数量的数字,剩下的数列要能够分成
K
(
K
≤
n
)
K(K\le n)
K(K≤n)个非空的区间,每个区间内求和,再对这
K
K
K个和取最大值,求这个最大值最小能是多少。
题解
二分 + DP。
二分答案。每次二分的检测为:能否分出
K
K
K个区间,每个区间求和小于二分值。
这一步用DP解决,
D
P
[
i
]
DP[i]
DP[i]表示前
i
i
i个数字最多能被分成多少个区间,且每个区间求和小于二分值。
设二分值为
L
i
m
Lim
Lim容易想到状态转移方程式:
D
P
[
i
]
=
m
a
x
{
D
P
[
j
]
+
1
}
(
j
<
i
&
S
u
m
(
j
+
1
,
i
)
≤
L
i
m
)
DP[i] =max\{DP[j]+1\}(j<i\ \&\ Sum(j+1,i)\le Lim)
DP[i]=max{DP[j]+1}(j<i & Sum(j+1,i)≤Lim)
因为
a
i
a_i
ai有正有负,合法的
j
j
j不是连续的。
令
S
[
i
]
S[i]
S[i]为前缀和,那么
j
j
j满足
S
[
i
]
−
S
[
j
]
≤
L
i
m
S[i]-S[j]\le Lim
S[i]−S[j]≤Lim,移项可得
S
[
j
]
≥
S
[
i
]
−
L
i
m
S[j]\ge S[i]-Lim
S[j]≥S[i]−Lim,对于所有前缀和离散化,做一个值域线段树或者反向做一个树状数组均可。
总复杂度
O
(
n
l
o
g
n
l
o
g
(
a
i
)
)
O(nlognlog(a_i))
O(nlognlog(ai))。勉强能满足这题的时限。
反思
在队伍里,我是做DP的,但是比赛时没有想出解法。
第一个二分提出之后,我没有注意到题目的时限,错误地认为需要
O
(
n
)
O(n)
O(n)检验,思考方向全在贪心和单调队列优化上面。
1006 Fansblog
题意
给出一个质数 P ( 1 0 10 ≤ P ≤ 1 0 14 ) P\ (10^{10}\le P\le10^{14}) P (1010≤P≤1014),小于 P P P的质数中最大的为 Q Q Q,求 Q ! m o d P Q!\ mod\ P Q! mod P。
题解
从
P
−
1
P-1
P−1开始枚举,用Miller-Robin素性测试,因为素数较为密集,可以很快枚举出
Q
Q
Q。
根据威尔逊定理可知,当
P
P
P为质数时,
(
P
−
1
)
!
≡
−
1
(
m
o
d
P
)
(P-1)! \equiv -1\ (mod\ P)
(P−1)!≡−1 (mod P),所以一路用逆元做除法,将
(
P
−
1
)
!
(P-1)!
(P−1)!除成
Q
!
Q!
Q!即可,因为模数很大,注意可能溢出的地方用__int128或者使用快速乘。
1007 Find the answer
题意
给出一个长为 n ( n ≤ 2 × 1 0 5 ) n\ (n\le2\times 10^5) n (n≤2×105)的数列 W i W_i Wi和数字 m ( m ≤ 1 0 9 ) m\ (m\le10^9) m (m≤109),要求输出 n n n个数字,第 i i i个数字表示在前 i − 1 i-1 i−1个数字中至少要把多少个 W i W_i Wi变成 0 0 0才能使得 ∑ j = 1 i W j ≤ m \sum_{j=1}^{i}Wj\ \le m ∑j=1iWj ≤m。
题解
离散化后,每次
i
i
i都尽量取最小的,取得越多越好,那么在线段树上做个二分即可。
复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)。
1008 Game
题意
给出
n
(
n
≤
1
0
5
)
n\ (n\le 10^5)
n (n≤105)个排列好的石堆
a
i
(
a
i
≤
1
0
6
)
a_i\ (a_i\le 10^6)
ai (ai≤106),先手会选择一个合法区间
[
L
,
R
]
[L,R]
[L,R] ,接着后手会在这个区间内再选择一个子区间
[
l
,
r
]
(
L
≤
l
≤
r
≤
R
)
[l,r]\ (L\le l\le r\le R)
[l,r] (L≤l≤r≤R),两人开始在这个子区间内进行Nim游戏。
操作一给出先手选择的
L
,
R
L,R
L,R,问先手此时是否必胜。
操作二是交换
P
O
S
POS
POS 和
P
O
S
+
1
POS+1
POS+1,不做回答。
题解
三维莫队+线段树。
首先,这些询问都是可以离线处理的,但是查找夹杂着修改,那么莫队需要加一维时间维度。
对于后手来说,他只用在
[
L
,
R
]
[L,R]
[L,R]中找到两个前缀异或和相等的位置即可。我们要做的无非是判断当前区间内是否存在相等即可,因为石堆数量不大,可以直接开个数组弄,即使数量大也可以离散化。
综上,总复杂度是三维莫队的复杂度
O
(
n
5
3
)
O(n^{\frac{5}{3}})
O(n35)。
1009 K Subsequence
题意
给出一个长为 n ( n ≤ 2 × 1 0 3 ) n\ (n\le2\times 10^3) n (n≤2×103)的数列,要求取出 k ( k ≤ 10 ) k\ (k\le10) k (k≤10)个不重叠的不下降子序列,使得所有取出来的数字和最大。
题解
谁能想到费用流就过了呢= =
超级源点向每个数字连费用为0的边。每个数字拆点,流量为1,费用为数字大小。从前往后,小的数字向大的数字连无费用的边。每个数字的出点向超级汇点连费用为0的边。拆超级源点或汇点,限流
k
k
k,保证取出序列的个数。
其实也不难想到,因为流量极小,做不了几次增广就结束了,复杂度反而出在最短路上,SPFA在稠密图上表现不好,Dijkstra才能过。(稍微手模了一下,貌似这种建图巨卡SPFA= =)。
总体复杂度大致为
O
(
10
n
l
o
g
(
n
)
)
O(10nlog(n))
O(10nlog(n))
1010 Sindar’s Art Exhibition
题意
给出一颗
n
(
n
≤
1
0
5
)
n\ (n\le10^5)
n (n≤105)的个节点的树,每个节点都有两个值
f
i
,
y
i
f_i,\ yi
fi, yi。
操作一,给出起点
s
s
s 和终点
t
t
t 以及初始值
x
x
x,每经过一个点,获得收益
f
i
⋅
x
f_i\cdot x
fi⋅x,,之后
x
x
x减去
y
i
y_i
yi,求总收益。
操作二,修改单点的
f
i
f_i
fi。
题解
树链剖分。剖分后转换为区间问题,之后用线段树维护,然后就是我队友发挥的 t i m e time time了。
1011 Squrirrel
题意
给出一棵有 n ( n ≤ 2 × 1 0 5 ) n\ (n\le2\times 10^5) n (n≤2×105)个节点的带有边权的树,你可以使一条边的权值变成 0 0 0,之后在树上找到一个点,使得这个点到树上每个点的最远距离最小。
题解
不难想到是树形DP,但是这题的状态设置和状态转移都出奇地复杂。
下面分享一下我的写法,基于HDU给的题解,实现上稍微添加了一些自己的想法。
M
a
x
1
[
i
]
[
j
]
Max1[i][j]
Max1[i][j]表示以
i
i
i 为根的子树中,离节点
i
i
i 第
j
j
j 远的距离是多少,这里的排名只需要维护前3大即可,但是要求来自
i
i
i 的不同儿子。
M
a
x
2
[
i
]
[
j
]
Max2[i][j]
Max2[i][j]表示
M
a
x
1
Max1
Max1中,第
j
j
j大的子树中,一条边归零后,最大距离是多少,这个只需要维护前2大。
维护
M
a
x
1
Max1
Max1不难,但是要注意保存来自哪一个儿子,方便后面分情况做
f
1
,
f
2
f1,f2
f1,f2。
M
a
x
2
Max2
Max2的维护也很简单,因为已经指定好了子树。分两个方案取
m
i
n
min
min,一个是删除当前边,儿子节点保留完整子树的最远距离;一个是保留当前边,子树的最远距离从儿子节点的
M
a
x
2
Max2
Max2转移过来。
令
f
1
,
f
2
f1,f2
f1,f2分别表示搜索到当前点时,以它为整个树的根,原来父节点的子树中,不归零和归零的最远距离,这两个值都要在父节点向子节点搜索时算出。
f
1
,
f
2
f1,f2
f1,f2的维护中,从父节点转移到儿子节点时,要注意当前是否转移到第一远子树或者第二远子树,这两个子树的
f
1
,
f
2
f1,f2
f1,f2计算方法略有不同。
令当前点为
x
x
x,与儿子连边的长度为
w
i
w_i
wi,想转移给儿子的为
F
1
,
F
2
F1,F2
F1,F2。
F
1
=
m
a
x
(
f
1
,
M
a
x
[
x
]
[
1
]
)
+
w
i
F1 = max(f1,Max[x][1]) + w_i
F1=max(f1,Max[x][1])+wi。
F
2
F2
F2懒得写等式了,分三个方案:
1、归零当前连边,在
f
1
f1
f1以及其他子树
M
a
x
1
[
x
]
Max1[x]
Max1[x]中取最远距离。
2、在父树上归零,在
f
2
f2
f2以及其他子树
M
a
x
1
[
x
]
Max1[x]
Max1[x]中取最远距离再加上当前边。
3、在其他子树中归零,在
f
1
f1
f1以及其他子树
M
a
x
2
[
x
]
Max2[x]
Max2[x]中取最远距离。
无论是转移给哪个子树,采取的方案都相同,但是区别在于
M
a
x
1
Max1
Max1中,你只能选取其他子树的方案,这也是为什么要记录前三大的数据。
答案当然就是在父树上归零和子树上归零取个最优啦,第一问的选取一个字典序最小的点也可以轻松维护。
总体复杂度
O
(
n
)
O(n)
O(n),但是因为是维护前三大,而且转移方案多,常数会非常大。
补题
- 1002
- 1004
- 1006
- 1007
- 1008
- 1009
- 1010
- 1011
读题
1001
1003
1005