数据结构好题汇总 (19/10/23)

HEOI2013 Segment
类似标记永久化,每个区间保留那个区间的最大线段,单点查的时候取 m a x max max 即可
找到线段的区间过后,考虑用它去覆盖这个区间的线段
如果全部比当前优,就覆盖
如果部分优,分类讨论:
1.左边高,中间高 ---- 左区间全部为当前,递归处理右区间
2.左边高,中间低 ---- 递归处理左区间
右边同理


AHOI2014 奇怪的计算器
考虑用线段树维护以每一个值为初始值的答案,同时维护最大最小来判上下界
需要支持:
1.区间加 2.区间乘 3.变形区间加,对每一个 x x x,加上 a i ∗ x a_i*x aix 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=cik1+xk2+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 2n 的网格的最小生成树
一个比较简单的做法是先求出两边的最小生成树,然后强制连两条横边
显然会存在一个环,这个环就是左边最靠右的竖边和右边最靠左的竖边连接而成的
断掉最大的,需要维护最靠右,最靠左的竖边的右,左的最大边
出问题了,如果左边的竖边删完了怎么办,那么最靠做的竖边就在右区间
还需要维护横边的最大值,同时维护竖边个数支持这个判断
还有问题,我们怎么知道删的是竖边?于是需要维护最左最右的竖边的权值,看一下它是不是 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(nn logn)


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 l1,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+(xl+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+(rl+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(l1)v+xv
考虑分块,块上打标记,维护 x x x 的系数以及常数项的系数
发现查前缀最大,就是查 m a x ( v a l x + k x ∗ x ) max(val_x+k_x*x) max(valx+kxx)
( 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 aix+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[aipre]+1
下一次的 a n s ′ = ∑ a i [ a i ≤ a n s ] + 1 ans'=\sum a_i[a_i\le ans]+1 ans=ai[aians]+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 ansans=pre<aiansai>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[ledgeur][ledgevr]
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} ansoutuansinu1
复杂度 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 KDTree,支持 p u s h d o w n pushdown pushdown 即可


Hiho 1236 Score
题意:5 维偏序,求5 维都小于它的数的个数, n ≤ 5 e 4 n\le 5e4 n5e4
好像可以 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 5nn ,时间 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

完结撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值