HEOI2013 Segment
类似标记永久化,每个区间保留那个区间的最大线段,单点查的时候取
m
a
x
max
max 即可
找到线段的区间过后,考虑用它去覆盖这个区间的线段
如果全部比当前优,就覆盖
如果部分优,分类讨论:
1.左边高,中间高 ---- 左区间全部为当前,递归处理右区间
2.左边高,中间低 ---- 递归处理左区间
右边同理
AHOI2014 奇怪的计算器
考虑用线段树维护以每一个值为初始值的答案,同时维护最大最小来判上下界
需要支持:
1.区间加 2.区间乘 3.变形区间加,对每一个
x
x
x,加上
a
i
∗
x
a_i*x
ai∗x 4.区间覆盖(超出限制的情况)
然后可以定义一个神奇的函数
f
(
k
1
,
k
2
,
k
3
)
f(k_1,k_2,k_3)
f(k1,k2,k3),整个区间的值会变化为
c
i
=
c
i
∗
k
1
+
x
∗
k
2
+
k
3
c_i=c_i*k_1+x*k_2+k_3
ci=ci∗k1+x∗k2+k3
对于覆盖
f
(
0
,
0
,
v
)
f(0,0,v)
f(0,0,v),对于区间加
f
(
1
,
0
,
v
)
f(1,0,v)
f(1,0,v),对于区间乘
f
(
v
,
0
,
0
)
f(v,0,0)
f(v,0,0),对于令一个区间加
f
(
1
,
v
,
0
)
f(1,v,0)
f(1,v,0)
每次覆盖暴力在线段树上二分找
>
r
,
<
l
>r,<l
>r,<l的位置
SDOI 2015 道路修建
题意:维护
2
∗
n
2*n
2∗n 的网格的最小生成树
一个比较简单的做法是先求出两边的最小生成树,然后强制连两条横边
显然会存在一个环,这个环就是左边最靠右的竖边和右边最靠左的竖边连接而成的
断掉最大的,需要维护最靠右,最靠左的竖边的右,左的最大边
出问题了,如果左边的竖边删完了怎么办,那么最靠做的竖边就在右区间
还需要维护横边的最大值,同时维护竖边个数支持这个判断
还有问题,我们怎么知道删的是竖边?于是需要维护最左最右的竖边的权值,看一下它是不是
m
a
x
max
max
上帝造题的七分钟2 / 花神游历各国
开根号几次就没了,于是并查集维护一段 1,直接跳过,树状数组单点修改
Hiho 1046 K 个串
类似超级钢琴,想到用堆维护
考虑维护以每个点为右端点的最大值,想到了主席树
在每一个右端点的主席树中,维护某个左端点到它的
s
u
m
sum
sum
考虑增加一个
r
r
r 的贡献,对
(
p
r
e
r
,
r
]
(pre_r,r]
(prer,r]的
l
l
l 有
a
r
a_r
ar 的贡献
BZOJ 3551
建出
K
r
u
s
k
a
l
Kruskal
Kruskal 重构树后用主席树维护子树信息即可
如果不强制在线的话可以按边权排序线段树合并
HNOI2012 永无乡
线段树合并,友好的入门题
BZOJ 3694 最短路
显然经过两条以上的非树边不会更优,于是只需考虑一条边
考虑非树边对哪些边有影响
显然就是两点到
l
c
a
lca
lca 上的点,不包括
l
c
a
lca
lca
对于路径
[
u
,
l
c
a
)
[u,lca)
[u,lca),该非树边的影响是
d
i
x
[
v
]
+
w
+
d
i
s
[
u
]
−
d
i
s
[
x
]
dix[v]+w+dis[u]-dis[x]
dix[v]+w+dis[u]−dis[x]
维护
m
i
n
(
d
i
s
[
v
]
+
w
+
d
i
s
[
u
]
)
min(dis[v]+w+dis[u])
min(dis[v]+w+dis[u]) 即可,另一边同理
BZOJ 2821 作诗
题意:
[
l
,
r
]
[l,r]
[l,r] 之间出现次数为偶数次的个数
首先可以预处理出块
[
l
,
r
]
[l,r]
[l,r] 之间的答案,对于两边的不超过
n
\sqrt n
n 个考虑
我们需要知道它在区间的出现次数,两边暴力加,中间预处理前缀和
s
u
m
[
i
]
[
j
]
sum[i][j]
sum[i][j] 表示
i
i
i 块之前
j
j
j 的出现次数,
O
(
n
n
)
O(n\sqrt n)
O(nn) 预处理
[
l
,
r
]
[l,r]
[l,r] 块的答案,固定左端点,右端点扫一遍也可以
O
(
n
n
)
O(n\sqrt n)
O(nn) 预处理
蒲公英
题意:区间众数,强制在线
同样预处理
[
l
,
r
]
[l,r]
[l,r] 块的答案,前缀和,两边统计一下出现次数即可
BZOJ 2741 L
分块,异或转前缀和,可持久化 0/1
t
r
i
e
trie
trie,预处理
l
l
l 块到
r
r
r 的答案,每次对于
l
l
l 块左边的剩余,暴力插
复杂度
O
(
n
n
l
o
g
n
)
O(n\sqrt nlogn)
O(nnlogn)
HEOI2013 ALO
考虑求每一个点作为次大值最大能在哪个区间
对于每个点,先求出它左边第一个大于它的,左边之后第一个大于它的,右边同理
定为
[
L
,
l
,
x
,
r
,
R
]
[L,l,x,r,R]
[L,l,x,r,R],那么它作为次大值的区间就是
(
L
,
r
)
(L,r)
(L,r) 或者是
(
l
,
R
)
(l,R)
(l,R)
排序后链表即可
HH 的项链
经典题,区间颜色个数
a
n
s
=
∑
i
=
l
r
p
r
e
i
<
l
ans=\sum_{i=l}^r pre_i<l
ans=∑i=lrprei<l,对于
l
−
1
,
r
l-1,r
l−1,r分别求出答案
求的时候离线,按端点排序,树状数组即可
BZOJ 2388
题意:区间加,区间前缀和最大值
考虑区间加对前缀和的影响,对于
[
l
,
r
]
[l,r]
[l,r] 的修改
v
a
l
x
=
v
a
l
x
+
(
x
−
l
+
1
)
∗
v
,
x
∈
[
l
,
r
]
val_x=val_x+(x-l+1)*v,x\in[l,r]
valx=valx+(x−l+1)∗v,x∈[l,r]
v
a
l
x
=
v
a
l
x
+
(
r
−
l
+
1
)
∗
v
,
x
∈
(
r
,
n
]
val_x= val_x+(r-l+1)*v,x\in(r,n]
valx=valx+(r−l+1)∗v,x∈(r,n]
第二个好办,第一个?
拆开
v
a
l
x
=
v
a
l
x
−
(
l
−
1
)
∗
v
+
x
∗
v
val_x=val_x-(l-1)*v+x*v
valx=valx−(l−1)∗v+x∗v
考虑分块,块上打标记,维护
x
x
x 的系数以及常数项的系数
发现查前缀最大,就是查
m
a
x
(
v
a
l
x
+
k
x
∗
x
)
max(val_x+k_x*x)
max(valx+kx∗x)
把
(
x
,
v
a
l
x
)
(x,val_x)
(x,valx) 看做点,斜率为
−
k
-k
−k 的线去切,维护一个上凸包即可
对于两边的零散点,查询暴力查,修改重建块的凸包
对于中间的点,修改打标记,查询在凸包二分
BZOJ3784 树上的路径
好题
考虑点分治,对于当前
d
f
s
dfs
dfs 到的一个点,它能拼接到的合法路径就是以当前分治中心为根的已经
d
f
s
dfs
dfs 过的子树中的点,也就是说对于当前这个点,考虑它的最大答案,就是之前
d
f
s
dfs
dfs 过的子树的最长
d
i
s
dis
dis 加上它的
d
i
s
dis
dis
发现之前
d
f
s
dfs
dfs 过的点如果到它就加入序列,这个点能拼接的点对应一段区间
于是可以定义 5 元组
(
d
i
s
,
l
,
r
,
p
o
s
,
m
a
x
)
(dis,l,r,pos,max)
(dis,l,r,pos,max),表示当前长度,能拼接的区间,区间的最大值,最大长度
类似超级钢琴,丢进堆按
d
i
s
+
m
a
x
dis+max
dis+max 排序取前 k 大即可
另外,点分出来的序列长度是
n
l
o
g
(
n
)
nlog(n)
nlog(n)那么长的,再套个
s
t
st
st 表,复杂度
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)
HNOI2009 梦幻布丁
好偏的数据结构
首先暴力就是对每个颜色维护一个链表,每次改颜色的时候暴力跳,判一下两边的颜色是不是要改的颜色
然后把这个链表接在后面
考虑优化暴力跳的过程,跳个数小的!
复杂度分析:每次需要用小的个数的时间合并成一个大,一个数如果被暴力跳了,那么它的连通块大小至少乘 2,所以一个点只会被跳
l
o
g
n
logn
logn 次
FJOI2016 神秘数
好题,就是难想
考虑暴力,把
[
l
,
r
]
[l,r]
[l,r] 排序扫一遍
假设当前可以表示的集合为
[
1
,
x
]
[1,x]
[1,x]
如果
a
i
≤
x
+
1
a_i\le x+1
ai≤x+1,值域可以变为
[
1
,
a
i
+
x
]
[1,a_i+x]
[1,ai+x]
否则 最小的无法被表示的就是
x
+
1
x+1
x+1
如何优化,不妨令当前的答案为
a
n
s
ans
ans
那么
≤
a
n
s
\le ans
≤ans 的数都可以被加进去
求出
≤
a
n
s
\le ans
≤ans 的数的和,定为
s
u
m
sum
sum
如果
a
n
s
>
s
u
m
+
1
ans > sum+1
ans>sum+1,那么凉凉
否则令
a
n
s
=
s
u
m
+
1
ans = sum + 1
ans=sum+1
复杂度分析:
不妨令上一次的
a
n
s
ans
ans 为
p
r
e
pre
pre
那么
a
n
s
=
∑
a
i
[
a
i
≤
p
r
e
]
+
1
ans=\sum a_i[a_i\le pre]+1
ans=∑ai[ai≤pre]+1
下一次的
a
n
s
′
=
∑
a
i
[
a
i
≤
a
n
s
]
+
1
ans'=\sum a_i[a_i\le ans]+1
ans′=∑ai[ai≤ans]+1
而
a
n
s
′
−
a
n
s
=
∑
p
r
e
<
a
i
≤
a
n
s
a
i
>
p
r
e
ans'-ans=\sum_{pre< a_i\le ans} a_i>pre
ans′−ans=∑pre<ai≤ansai>pre
也就是说
a
n
s
′
>
a
n
s
+
p
r
e
ans'>ans+pre
ans′>ans+pre
比斐波那契增长的还快
现在的问题就是如何求小于等于某个数的数的和
主席树即可
复杂度
O
(
n
l
o
g
(
n
)
l
o
g
(
∑
a
i
)
)
O(nlog(n)log(\sum a_i))
O(nlog(n)log(∑ai))
Hihocoder 1145
联通块个数 = 点数 - 边数
边数 =
∑
e
d
g
e
[
l
≤
e
d
g
e
u
≤
r
]
[
l
≤
e
d
g
e
v
≤
r
]
\sum_{edge}[l\le edge_u\le r][l\le edge_v \le r]
∑edge[l≤edgeu≤r][l≤edgev≤r]
对
e
d
g
e
u
edge_u
edgeu 建主席树,
e
d
g
e
v
edge_v
edgev 为下标即可
HNOI2015 接水果
考虑一个水果会被哪些接到,如果
(
u
,
v
)
(u,v)
(u,v) 转了弯
那么需要
x
∈
[
i
n
u
,
o
u
t
u
]
,
y
∈
[
i
n
v
,
o
u
t
v
]
x\in[in_u,out_u],y\in [in_v,out_v]
x∈[inu,outu],y∈[inv,outv]
如果
(
u
,
v
)
(u,v)
(u,v) 没有转弯,那么需要
x
∈
[
i
n
u
,
o
u
t
u
]
,
y
∈
[
1
,
i
n
v
)
⋃
(
o
u
t
v
,
n
]
x\in[in_u,out_u],y\in[1,in_v)\bigcup(out_v,n]
x∈[inu,outu],y∈[1,inv)⋃(outv,n]
于是问题转换为平面上有很多点,问矩阵或者两个矩阵和起来的第 k 大
考虑整体二分,每次把
≤
m
i
d
\le mid
≤mid 的点插入,然后变成查个数
可以先按
x
x
x 排序,然后
[
i
n
u
,
o
u
t
u
]
[in_u,out_u]
[inu,outu] 转成
a
n
s
o
u
t
u
−
a
n
s
i
n
u
−
1
ans_{out_u}-ans_{in_u-1}
ansoutu−ansinu−1
复杂度
O
(
n
l
o
g
2
(
n
)
O(nlog^2(n)
O(nlog2(n))
矩阵乘法
整体二分,二维树状数组查个数即可
BZOHJ4154 Generating Synergy
考虑
d
f
s
dfs
dfs序,被染色的那些点,显然
i
n
x
∈
[
i
n
u
,
o
u
t
u
]
,
d
e
p
x
∈
[
d
e
p
u
,
d
e
p
u
+
y
]
in_x\in[in_u,out_u],dep_x\in[dep_u,dep_u+y]
inx∈[inu,outu],depx∈[depu,depu+y]
是一个矩阵,于是问题转换为矩阵染色,区间查询
写一个
K
D
−
T
r
e
e
KD-Tree
KD−Tree,支持
p
u
s
h
d
o
w
n
pushdown
pushdown 即可
Hiho 1236 Score
题意:5 维偏序,求5 维都小于它的数的个数,
n
≤
5
e
4
n\le 5e4
n≤5e4
好像可以
n
l
o
g
5
(
n
)
nlog^5(n)
nlog5(n)…
考虑
b
i
t
s
e
t
bitset
bitset,对于每一维排序,预处理出比一个数小的数的集合,最后与一下的
s
i
z
e
size
size 就是答案
但是空间要凉
想到了分块,对于每一维,处理出比一个块小的数的集合
空间
5
∗
n
n
5*n\sqrt n
5∗nn,时间
n
n
64
\frac{n\sqrt n}{64}
64nn,做法是开一个全局
b
i
t
s
e
t
bitset
bitset,然后每个块暴力赋值
询问:对于之前的块,暴力与,复杂度
n
64
\frac{n}{64}
64n
对于剩下的
5
n
5\sqrt n
5n 个数,每一维用
b
i
t
s
e
t
bitset
bitset 求一遍暴力与
复杂度
5
n
+
n
64
5\sqrt n+\frac{n}{64}
5n+64n
完结撒花