[ZJOI2017]仙人掌
发现可以把一个仙人掌看做所有环组成的图,如果不是环而是单个边,我们可以手动给它填一条边变成环
考虑一棵树怎么做?
就是在树上选若干条互不相交的链的方案数,考虑树形
d
p
dp
dp
f
i
f_{i}
fi 表示到 i 的子树的方案数,
g
i
g_i
gi 表示一个点有 i 条边相连,两两配对或者单身的方案数
g
i
=
g
i
−
1
+
(
i
−
1
)
∗
g
i
−
2
g_i=g_{i-1}+(i-1)*g_{i-2}
gi=gi−1+(i−1)∗gi−2,前面表示当前边单身,后面表示当前边配对
考虑转移的时候无论如何都会从下面窜出来一条,还要考虑父亲那条边,于是有
f
u
=
∏
f
v
∗
g
∣
s
o
n
∣
+
1
f_u=\prod f_v*g_{|son|+1}
fu=∏fv∗g∣son∣+1,根不算父亲那条边就可以了
[ZJOI2017]树状数组
考虑他写的跟正确的有什么变化
如果用后缀表示,首先他求的是
S
r
−
S
l
−
1
S_{r}-S_{l-1}
Sr−Sl−1,而正确的是
S
l
−
S
r
+
1
S_{l}-S_{r+1}
Sl−Sr+1
发现
S
r
−
S
l
−
1
=
−
A
l
−
1
+
S
r
−
S
l
S_r-S_{l-1}=-A_{l-1}+S_r-S_l
Sr−Sl−1=−Al−1+Sr−Sl,
S
l
−
S
r
+
1
=
S
l
−
S
r
+
A
r
S_l-S_{r+1}=S_l-S_r+A_r
Sl−Sr+1=Sl−Sr+Ar
于是求的就是
A
l
−
1
A_{l-1}
Al−1 与
A
r
A_r
Ar 相同的概率
考虑直接维护
a
i
a_i
ai与
a
j
a_j
aj 相等的概率
如果
a
i
∈
[
1
,
l
−
1
]
a_i \in [1,l-1]
ai∈[1,l−1],
a
j
∈
[
l
,
r
]
a_j \in [l,r]
aj∈[l,r] ,有
1
l
e
n
\frac{1}{len}
len1 的概率改变
如果
a
i
∈
[
l
,
r
]
a_i \in [l,r]
ai∈[l,r],
a
j
∈
[
l
,
r
]
a_j \in [l,r]
aj∈[l,r],有
2
l
e
n
\frac{2}{len}
len2 的概率改变
如果
a
i
∈
[
l
,
r
]
a_i \in [l,r]
ai∈[l,r],
a
j
∈
[
r
+
1
,
n
]
a_j \in [r+1,n]
aj∈[r+1,n],有
1
l
e
n
\frac{1}{len}
len1 的概率改变
然后可以用线段树维护一下这个矩阵,加上一个概率的时候需要合并
假如原来有 p 的概率相同,当前有 q 的概率改变,那么最后相同的概率就是
p
∗
(
1
−
q
)
+
(
1
−
p
)
∗
q
p*(1-q)+(1-p)*q
p∗(1−q)+(1−p)∗q
我们注意到,find 函数中如果 x = 0,直接返回 0
问的是前缀和后缀相同的概率
对于
[
l
,
r
]
[l,r]
[l,r] 的修改,
[
1
,
l
−
1
]
,
[
r
+
1
,
n
]
[1,l-1], [r+1,n]
[1,l−1],[r+1,n]一定改变,
[
l
,
r
]
[l,r]
[l,r] 不变的概率为
1
l
e
n
\frac{1}{len}
len1
所以在维护二维线段树的同时需要在维护一棵一维的线段树
[BJOI2017]树的难题
考虑点分,如何合并?
把子树按颜色排序,维护两棵线段树,与到分治中心的距离为下标,一棵维护当前颜色,一棵维护之前出现的颜色,线段树可以写成单点修改区间查最大
[BJOI2017]魔法咒语
代码分块,对于
L
≤
100
L\le 100
L≤100时,和
L
≤
2
L\le2
L≤2分别考虑
前面那个就是一个比较裸的 dp,后面那个可以用矩阵乘,
由于
L
≤
2
L\le 2
L≤2,于是要把
f
i
f_{i}
fi和
f
i
−
1
f_{i-1}
fi−1都放进去
[HNOI2017]单旋
手玩一下
s
p
l
a
y
splay
splay 到根,发现树的形态基本不变,于是就可以用
L
C
T
LCT
LCT 模拟了,顺便维护一下
d
e
p
dep
dep
插入操作用 set 查一下该插到哪儿,然后就可以慢慢去
d
e
b
u
g
debug
debug 了
[HNOI2017]影魔
考虑一个点 i ,左边第一个比它大的
l
i
l_i
li,右边第一个比它大的
r
i
r_i
ri
那么区间
[
l
,
r
]
[l,r]
[l,r] 有
p
1
p_1
p1 的贡献
区间
[
l
+
1
−
−
i
,
r
−
1
]
[l+1--i,r-1]
[l+1−−i,r−1] 有
p
2
p_2
p2 的贡献
区间
[
l
+
1
,
i
+
1
−
−
r
]
[l+1,i+1--r]
[l+1,i+1−−r] 有
p
2
p_2
p2 的贡献
于是我们可以把这些操作排序,扫到
l
i
l_i
li 的时候更新一下
r
i
r_i
ri
扫到
l
i
+
1
l_i+1
li+1 的时候更新一下
i
+
1
−
−
r
i+1--r
i+1−−r
然后将询问离线,考虑一个
[
l
,
r
]
[l,r]
[l,r]的询问,我们可以将刚刚排序的在
[
l
,
r
]
[l,r]
[l,r] 之间的加一遍,然后查区间
[
l
,
r
]
[l,r]
[l,r]的答案,反过来想就是 r 的答案 - l-1 的答案就可以了
[SDOI2017]遗忘的集合
背包的套路:考虑生成函数,
a
i
a_i
ai 表示 i 是否出现在集合中
则生成函数是
f
(
x
)
=
∑
(
1
1
−
x
i
)
a
i
f(x)=\sum(\frac{1}{1-x^i})^{a_i}
f(x)=∑(1−xi1)ai
两边取 ln,
−
l
n
(
f
(
x
)
)
=
∑
a
i
∗
l
n
(
1
−
x
i
)
-ln (f(x))=\sum a_i*ln(1-x^i)
−ln(f(x))=∑ai∗ln(1−xi)
对
l
n
(
1
−
x
i
)
ln(1-x^i)
ln(1−xi) 求导,类似付公主的背包,可以得到
l
n
(
f
(
x
)
)
=
∑
T
=
1
(
∑
d
∣
T
a
d
∗
d
T
)
x
T
ln(f(x))=\sum_{T=1} (\sum_{d|T}a_d*\frac{d}{T})x^T
ln(f(x))=∑T=1(∑d∣Tad∗Td)xT
ln 后调和级数枚举一下贡献即可