首页 > 其他分享 >数据结构总结

数据结构总结

时间:2024-01-26 15:26:41浏览次数:25  
标签:总结 trie 线段 离线 fa 区间 数据结构 莫队

P4198 楼房重建

非常好题目,首先你显然能够得到一个楼房看得见的条件:当斜率严格大于之前的所有斜率时,这栋楼房可以被看见。

接着我们考虑线段树 \(sum_i\) 维护 \([l,r]\) 从 \(l\) 出发可以看到的楼房数。我们发现重点在于 push_up 函数的实现,设左区间为 \(ls\),右区间为 \(rs\)。 那么 \(sum_s\) 必然要加上 \(sum_{ls}\)。接着考虑右区间,如果 \(mx_{ls} < a_{mid+1}\) 那就直接加上右区间答案;如果 \(mx_{rs} \leq mx_{ls}\) 直接返回 \(0\);如果右区间的左区间的最大值大于左区间的最大值,那就递归下去并加上右区间的右区间的答案;不然就递归右区间。

P7470 岛屿探险

首先看到下面给的部分分,就提示你分类讨论:一种是 \(b>d\),另外一种是 \(b \leq d\)。

1. \(b > d\)

这种你会发现这个只跟 \(d\) 有关,你对所有的 \(a\) 建一颗 trie 树然后遍历就行了。

具体地,就是对于当前 \(d\) 在二进制下第 \(i\) 位为 \(p\),\(c\) 在二进制下第 \(i\) 位为 \(q\)。若 \(p\) 为 \(1\),那我在这一位上如果选择 \(a\) 在这一位上为 \(q\),后面就都不需要继续考虑,直接加上有多少个这样的 \(a\)。接着继续向下遍历即可。

2. \(b \leq d\)

这种乍眼一看好像不好解决,但你发现这个跟第一种是同构的,只需将所有需要考虑的 \(c\) 建一颗 trie 就行了,做法与第一种类似。


现在我们知道了如何解决这两种操作,但如何在有限时间内求出所有答案?我们考虑线段树分治,将每个查询 \([l,r]\) 拆开放到线段树上,这样就可以对所有查询同时处理了。

但是,\(b\) 和 \(d\) 都有多个,所以我们考虑双指针。先将岛屿和询问分别按照 \(b\) 和 \(d\) 的大小升序排列,接着遍历 \(d\),每次再把不符合 \(b>d\) 的 \(b\) 剔除 \(a\) 的 trie,再讲这个 \(a\) 去遍历一遍 \(c\) 的 trie 即可。

复杂度: \(O(nlognlogw)\)

P6018 Fusion tree

思路很简单,只需要把父亲和儿子分开考虑就行,维护儿子需要全局加 \(1\) 的操作,trie 树按位从小到大建,每次交换 \(1\) 和 \(0\) 两棵子树,具体代码:

inline void modify(int u){
	swap(trie[u][0],trie[u][1]);
	if(trie[u][0]) modify(trie[u][0]);
	push_up(u);
}

P4768 归程

题目可以转化为当前能走到的点中与 \(1\) 最近的距离,所以先从 \(1\) 出发跑最短路。

而当且能走的边为 \(> p\) 的边,而我们只需要知道这个点是否能从我们的出发点到达,所以用 kruskal 重构树,先求出最大生成树,然后将每个边当成合并两个连通块的点,以最后加入的点为根,点权为原来边权,那建出来的树就具备以下性质:子树内所有点两两点的所有路径中的边权最小值大于等于当前这个节点的权值,代码具体如下:

int now=n;
for(int i=1;i<=m;i++){
	int x=getfa(e[i].u),y=getfa(e[i].v);
	if(x==y) continue;
	now++;
	a[now]=e[i].w;
	ed[now].push_back(x),ed[now].push_back(y);
	fa[x]=fa[y]=now;
}

最后倍增查找即可。

P3402 可持久化并查集

重点在将 \(fa\) 数组可持久化,注意要按秩合并,要么按 \(siz\) 要么按 \(height\)。

和可持久化线段树相同,每个版本保留未更改的部分压缩空间。

P8253 如何正确地排序

首先对于 \(m=3\) 的情况,可以求每一个值得贡献,而对于 \(a_{x,i}\) 有贡献,当且仅当:

设另外两行为 \(y\),\(z\)。

则可以得到:

\(\left\{ \begin{aligned} &a_{x,i}+a_{x,j} < a_{y,i}+a_{y,j}\\ &a_{x,i}+a_{x,j} < a_{z,i}+a_{z,j} \end{aligned} \right. \)

\(\left\{ \begin{aligned} &a_{x,i}+a_{x,j} > a_{y,i}+a_{y,j}\\ &a_{x,i}+a_{x,j} > a_{z,i}+a_{z,j} \end{aligned} \right. \)

这就是一个二维偏序,就可以做了。

那么对于 \(m=4\),就是三维偏序,可以 cdq 分治做;也可以找哪一些点没有贡献,就是二维偏序了,总贡献减去这些点即可。

P5163 WD与地图

首先考虑将删边变为加边。

接着发现可以二分一条边能把两个强连通块合并的时间,于是整体二分做就行了。

P5609 对数据结构的爱

挺有思维难度的一道题,你发现题意就是未经过“取模”的和减去有“取模”位置的个数再乘以 \(p\)。

首先发现可以维护在 \([l,r]\) 这一个区间中最小需要前缀值为多少,能使有“取模”的位置有 \(x\) 个,记这个前缀值为 \(w_x\),而这个序列 \(w\) 显然是不减的。然后你就可以放到线段树上维护了,可是问题在于如何将两个不减的序列合并。

显然,\(w_x - w_{x-1} \ge p\)。

然后我们对于左区间有 \(x\) 个,右区间有 \(y\) 个位置,在合法的情况下,得到的前缀值 \(f(x,y)=max(c_y - leftsum + px, c_x)\),至于合法,就是最大的左区间有 \(x\) 个的值减去 \(px\) 之后依旧大于等于 \(c_y\)。

然后就有一个性质: \(f(x,y) \ge f(x+1,y-1)\)

证明:

\(f(x,y)=max(c_y - leftsum + px, c_x)\)

\(f(x+1,y-1)=max(c_{y-1} - leftsum + p(x+1), c_{x+1})\)

\(c_{x+1}-c_{x} \ge p\)

\(c_y - c_{y-1} -p \ge 0\)

证毕。

然后就可以在 \(O(n)\) 的时间内合并了。

P5280 线段树

首先你肯定会想到维护当前这个点值为 \(1\) 的个数,那么对于一个 \([l,r]\) 的修改,有以下几种点,设这个点 \(i\) 在线段树上表示的区间是 \([L,R]\)。

  1. \([L,R] \cap [l,r] \neq \oslash, [L,R] \nsubseteq [l,r]\)

  2. \([L,R] \subseteq [l,r], fa_i \nsubseteq [l,r]\)

  3. \([L,R] \cap [l,r] = \oslash, fa_i \cap [l,r] \neq \oslash\)

  4. \([L,R] \subseteq [l,r], fa_i \subseteq [l,r]\)

  5. \([L,R] \cap [l,r] = \oslash, fa_i \cap [l,r] \neq \oslash\)

然后你会发现若一个区间能被赋为 \(1\),当且仅当它到根这条链上有值为 \(1\) 的点。

所以维护两个数组 \(f,g\),\(f_u\) 表示这个点 \(u\) 值为 \(1\) 的个数, \(g_u\) 表示点 \(u\) 到根没有值为 \(1\) 的个数。

设 \(t\) 为第 \(t\) 次修改操作。

那么对于第一种,就有转移:

\(f_u = f_u\),\(g_u = g_u + 2^{t-1}\)

第二种转移:

\(f_u =f_u +2^{t-1}\),\(g_u =g_u\)

第三种转移:

\(f_u =f_u + (2^{t-1} -g_u)\),\(g_u =2g_u\)

第四种转移:

\(f_u = 2f_u\),\(g_u = g_u\)

第五种转移:

\(f_u = 2f_u\),\(g_u = 2g_u\)

然后线段树上维护就行了。

根号数据结构

莫队+离线维护更改值 \(\to\) 二次离线莫队。

非常好理解的东西,比如说查询区间逆序对个数,在莫队的时候加一个点或删一个点显然是无法做到 \(O(1)\) 的,这时候我们就把问题离线下来,比如右端点 \(r\) 向外扩展,那么设贡献为 \(F(r+1,l,r)\) 表示 \(r+1\) 这一个点将和当前的 \([l,r]\) 做贡献,那么可以把这个贡献写成 \(F(r+1,1,r) - F(r+1,1,l-1)\) 的形式,由于莫队扩展以及收缩的的操作数是 \(O(n \sqrt n)\) 的,所以可以离线下来把值的贡献计算出来。

例题也不多,就列三个出来,感觉都挺板的。

【模板】莫队二次离线(第十四分块(前体))

【LnOI2019】来者不拒,去者不追

【Ynoi2019 模拟赛】 Yuno loves sqrt technology II

标签:总结,trie,线段,离线,fa,区间,数据结构,莫队
From: https://www.cnblogs.com/Cyan0826/p/17989458

相关文章

  • 29-数据结构介绍
          ......
  • 高效又稳定的ChatGPT大模型训练技巧总结,让训练事半功倍!
    高效又稳定的ChatGPT大模型训练技巧总结,让训练事半功倍!前言近期,ChatGPT成为了全网热议的话题。ChatGPT是一种基于大规模语言模型技术(LLM,largelanguagemodel)实现的人机对话工具。现在主流的大规模语言模型都采用Transformer网络,通过极大规模的数据进行自监督训练。但是,如......
  • 1月26日总结(服务外包杯大模型总结)
    在本地部署了chatglm3大模型的cpu运行版本,但是运行速度太缓慢。在阿里云服务器部署了langchain-chatglm大模型,还有一个langchain-chatchat版本,之后会尝试一下。观看了一些视频,有一些想法:赛题官方答复可以做多个城市的旅游知识库。可以添加多模态,生成图片音频,这可以作为一个......
  • vue中动态添加style样式的几种写法总结
    项目中可能会需要动态添加style行内样式,但是在长期维护的项目里面,尽量要避免使用。注意:1、凡是有-的style属性名都要变成驼峰式,比如font-size要变成fontSize。2、除了绑定值,其他的属性名的值要用引号括起来,比如backgroundColor:'#00a2ff'而不是backgroundColor:#00a2ff。......
  • 做题记录(数据结构+整体二分专题)
    情报传递对于每一个操作打上时间戳,对于\(T\)时刻的询问,即为询问路径上比\(T-c\)的值小的数有几个。直接树剖上维护权值树状数组即可。宝石给定一棵树,\(n\)个顶点,每个点有一个宝石,类型为\(W_i\),约定\(W_i\lem\)。你有一个收集器,可以收集至多\(c\)个宝石,并且收集......
  • Kafka 特性总结
    Kafka特性可总结如下:1.高可用Kafka0.8以前是没有高可用机制的。Kafka0.8以后,通过副本机制来实现高可用,基于副本机制实现Kafka的高可用。2.持久性Kafka集群接收到Producer发过来的消息后,将其持久化到磁盘。此外,还支持数据备份。3.数据不易丢失通过合理的配置,Ka......
  • 今日总结
    Spark四大特点Spark使用Scala语言进行实现,它是一种面向对、函数式编程语言,能够像操作本地集合一样轻松的操作分布式数据集。Spark具有运行速度快、易用性好、通用性强和随处运行等特点。速度快由于ApacheSpark支持内存计算,并且通过DAG(有向无环图)执行引擎支持无环数据流,所......
  • js中数组反转的方法总结
    1.常用的方法reverse()[1,2,3,4].reverse()  //[4,3,2,1]2.采用for循环方式使用递减循环遍历的方式,将元素一次存入新的数组中,新数组就是反转后的新数组constdataRef=[1,2,3,4]constnewArr:any[]=[]for(leti=dataRef.length-1;i>=0;i--){ne......
  • 【数据结构】72变的双端队列
    双端队列前言大家好,很高兴又和大家见面啦!!!在前面的篇章中,咱们详细介绍了队列这种新的数据结构,现在我们简单的回顾一下队列的三要素——数据的逻辑结构、数据的存储结构以及数据的运算。数据的逻辑结构队列的数据元素在逻辑上是呈现线性结构,也就是说队列也是一种线性表,只不过是一种......
  • 李宏毅《机器学习》总结 - CNN
    使用场景:对图片进行分类首先,将图片变成向量。例如,对于一个彩色的\(N\timesN\)(这个N指的是像素个数)图片,其对应着一个\(N\timesN\times3\)的矩阵(其中3是图片的channel,在彩色图片中,每个像素由RGB构成,因此channel为3)一个初始的想法将这个矩阵拉长,变成一个向量,然后......