数据结构
文章平均质量分 82
AC_Arthur
Die luft der Freiheit weht
展开
-
manacher算法
ACM退役很久了, 不过仍然喜欢解决一些很酷的算法。至此之后, 这里将会是一个纯净的算法讨论阵地, 和比赛无关, 但是希望能将算法的原理和做法讲解明白。很后悔在做ACM的时候没有这么做。博客推荐这个, 可以很快了解一下这个算法的做法:点击打开链接那么我还是简单说一下。我们从左往右扫描字符串枚举中点。算法维护了一个最右边的点, 这个是当前存在的回文串的最右边能到原创 2017-09-05 19:37:02 · 895 阅读 · 0 评论 -
HDU 5441 Travel(并查集)
题目链接:点击打开链接思路:题目要求有多少对点(a, b)使得a到b的最短路上最长边不超过x。 我们将边从小到大排序, 用并查集来维护关系, 这样, 对于当前加入集合的一条边(a, b),权值为c, 他就是当前集合的最长边, 那么不大于c的对数就是就是这两个集合的个数的组合。 预处理一下即可。细节参见代码:#include #include #include #include原创 2016-07-31 13:52:26 · 622 阅读 · 0 评论 -
Codeforces Round #305 (Div. 1) B. Mike and Feet(并查集)
题目链接:点击打开链接思路:我们把元素从大到小排序, 从大到小依次合并区间, 对于第i个数, 如果他相邻左边的数比他大就合并, 相邻右边也一样。这样, 我们就求出了第i个数为最小值的最大区间。 更新答案即可。细节参见代码:#include #include #include #include #include #include #include #include #in原创 2016-07-17 16:53:52 · 1198 阅读 · 0 评论 -
POJ 2796 Feel Good(并查集)
题目链接:点击打开链接思路:该题转化一下, 就是枚举每一个数, 找到以这个数为最小值的最大区间(因为没有负数)。 那么一个办法是预处理出每一个数左边第一个比他大的数的位置, 和右边第一个比他大的数的位置, 这个可以用构造单调栈的线性算法处理出来: 我们构造一个单调上升栈, 标记栈里每个元素在实际中的位置, 加入一个元素a[i]的时候, 如果栈顶元素大于他, 那么将栈顶元素出队列, i就是原创 2016-07-15 16:55:08 · 1245 阅读 · 0 评论 -
SPOJ 417 The lazy programmer(优先队列)
题目链接:点击打开链接思路:一开始一直在想, 对于当前的一个任务i,他到底应该花费多少合适, 因为会影响后面的决策。 后来才想明白一件事, 对于当前这个任务, 减少他的时间和减少之前任意一个任务的时间是等价的, 那么我们当然优先减少那些a比较大的。 如果当前这个任务无法完成, 那么就在之前的所有任务中找a尽量大的来减少时间。 显然, 是一定有解的。细节参见代码:#include原创 2016-07-04 21:27:36 · 1500 阅读 · 0 评论 -
UVA 536 - Tree Recovery(二叉树重建)
题目链接:点击打开链接思路: 二叉树有三种遍历方式, 体现在代码中, 就是:保存结点值如果是在递归前保存, 就是前序, 在递归完左子树后保存, 就是中序, 递归完左右子树后保存就是后序。由中序加上另一种, 我们可以写出剩下一种。 由前序遍历或者后序遍历, 我们可以依次知道父结点是什么, 然后在中序遍历中找到对应值, 那么该结点的左右子树分别在中序遍历中该位置的左右。 递归解决即可。原创 2016-07-14 15:34:22 · 1264 阅读 · 0 评论 -
Codeforces Round #271 (Div. 2) E. Pillars(线段树+DP)
题目链接:点击打开链接思路:类似于最长上升子序列, 我们很容易得到一个n^2的算法, 但是时间复杂度无法承受。可以发现, |a[i]-a[j]| >= d相当于对于每个j, 找到一个i = a[j]+d)中最大的dp[i]。 我们将数字大小离散化之后做线段树下标, 然后维护一个区间最大值就行了。 时间复杂度O(nlogn)细节参见代码:#includeusing namesp原创 2016-07-13 14:03:57 · 536 阅读 · 0 评论 -
SGU 311. Ice-cream Tycoon(平衡树)
题目链接:点击打开链接思路:最简单的思路是, 维护一棵平衡树, 以单价作为键值, 维护一个结点个数的信息。 然后类似寻找第K小的方法找到第n个小的价值处, 顺便维护总价值, 判断是否happy。然后就是删除操作。 我们从新从根结点开始, 沿路删除可以删除的子树就行了。 由于每次删除都是删除的叶子结点处, 所以不需要旋转操作。细节参见代码:#include #include原创 2016-07-10 20:53:48 · 1591 阅读 · 0 评论 -
ZOJ 2112 Dynamic Rankings(线段树套treap求动态第K大)
题目链接:点击打开链接思路:我们都知道, treap可以维护整个区间内的数的大小关系, 那么我们在线段树的每个节点上建一棵treap, 那么对于一个n个数的每一个数, 他都会经历logn个结点,所以总的结点数是n * logn。 然后二分答案ans, 询问区间内一个防止超内存的黑科技:开一个数组做内存池。细节参见代码:#include #include #include #i原创 2016-05-16 17:04:22 · 3128 阅读 · 0 评论 -
POJ 1442 Black Box(treap树指针实现)
题目链接:点击打开链接思路:本来不想用指针实现的, 但是在做动态第K小的题目时发现, 如果不用动态申请内存的方式, 数组根本开不下。思路和静态数组模拟是一样的。细节参见代码:#include #include #include #include #include #include #include #include #include #include #incl原创 2016-05-15 21:58:15 · 1300 阅读 · 0 评论 -
POJ 1442 Black Box(treap树)
题目链接:点击打开链接思路:treap树模板题, 可以动态维护一个有序表, 支持在O(logN)的时间内完成插入、删除一个元素和查找第K大元素的任务。 当然, treap树能做到的还远远不止这些, 常常与其他数据结构嵌套。treap树是一种平衡二叉搜索树, 既满足堆的条件, 又满足排序二叉树的条件。细节参见代码:#include #include #include #incl原创 2016-05-13 20:22:31 · 4259 阅读 · 0 评论 -
POJ 2104 K-th Number(主席树)
题目链接:点击打开链接细节参见代码:#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define Max(a,b) ((a)>(b)?(a原创 2016-05-12 22:29:18 · 3973 阅读 · 0 评论 -
HDU 2665 Kth number(划分树)
题目链接:点击打开链接思路:划分树模板题。细节参见代码:#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#define Max(a,b) ((a)>(b)?(a):(原创 2016-04-15 16:35:17 · 4380 阅读 · 0 评论 -
ZOJ 2334 Monkey King(左偏树)
题目链接:点击打开链接思路:左偏树模板题, 需要维护集合关系, 这个可以用并查集很方便的维护, 另外需要用一个数组来维护每个点所在的左偏树编号。细节参见代码:#include#include#include#include#include#include#include#include#include#include#include#include#includ原创 2016-04-14 21:53:08 · 3810 阅读 · 0 评论 -
UVA 11997 - K Smallest Sums(多路归并)
题目链接:点击打开链接思路:多路归并。 用贪心的规则, 我们先考虑两个数组的情况, 如果将两个数组从小到大排序, 那么我们先将数组a的所有元素加上数组b的最小的元素, 然后放入优先队列。 因为是事先排好序的, 所以其中肯定有一个是最小的,那么当这个数取出来之后, 如何保证队列头上时次小的呢? 我们发现, a数组的所有元素都用上了, 而且是和b数组中最小的数相加得到的, 所以, 当a[0]+b[原创 2016-04-27 21:24:14 · 4075 阅读 · 2 评论 -
HDU 3047 Zjnu Stadium(带权并查集)
题目链接:点击打开链接思路:注意, 行数是无限的, 因此, 两个人可以同时都相距另一个人x远(相距x列, 不在同一行),也就是说, 出现矛盾的唯一地方就是在于, 现在说的两个人相距的距离和之前说的矛盾。 那么怎么判断矛盾呢, 由于每个人之间有间接关联性, 因此, 我们需要处理一个集合的距离问题 , 所以用带权并查集就可以很好的处理。细节参见代码:#include#include原创 2016-04-14 17:23:59 · 2836 阅读 · 0 评论 -
Codeforces Round #250 (Div. 2) (D. The Child and Zoo(并查集))
题目链接:点击打开链接题意:给你一个n个点, m条边的图, 每个点有一个点权值, 我们定义f(p, q)表示p点到q点的一条路径, 要求这条路径上的最小点权尽量大, 其值等于最小点权值。 求任意一对点的f值之和除以n * (n - 1) , 即平均值。思路: 其实转化一下, 就是要先求最大生成树, 那么路径一定在树种, 且唯一。 那么我们从大到小来, 每次将两个集合合并的时候, 那么A原创 2016-03-11 19:46:24 · 1305 阅读 · 0 评论 -
Codeforces Round #363 (Div. 2)题解
这场比赛水了4个题。 部分题解如下:A. Launch of ColliderA题:我们每次遇到一个L, 就找到上一个R,他们肯定是比较近的, 这些中最近的就是最近的辣。细节参见代码:#include #include #include #include #include #include #include #include #include #inclu原创 2016-07-20 20:49:59 · 1447 阅读 · 0 评论 -
UVA live 3938 - "Ray, Pass me the dishes!"(线段树)
题目链接:点击打开链接该题需要深刻理解线段树的特点:任意一个父结点所表示的区间都是两个儿子区间的并, 且儿子区间的交为空集。那么我们可以采用分治的思想: 一段区间的最大连续和要么来自左半边, 要么来自右半边, 或者一半在左一半在右。细节参见代码:#include#include#include#include#include#include#include#inclu原创 2016-08-27 18:23:27 · 696 阅读 · 0 评论 -
HDU 5818 Joint Stacks(左偏树)
题目链接:点击打开链接思路:该题的关键是怎么把两个栈合并, 我们可以使用一种叫左偏树的数据结构, 满足堆的性质和集合的性质,支持在O(logn)的复杂度下进行删除堆顶元素, 插入一个元素,合并两个堆。细节参见代码:#include using namespace std;typedef pair P;const int maxn = 152400;P v[maxn];in原创 2016-08-10 19:57:23 · 936 阅读 · 2 评论 -
Codeforces Round #396 (Div. 2)D. Mahmoud and a Dictionary(带权并查集)
题目链接:点击打开链接思路:带权并查集水题。 带权并查集可以知道在一个集合里的两点间距离。那么这种同义反义关心恰好对应距离的奇偶。附上一图:这就是合并的过程。细节参见代码:#include #include #include #include #include #include #include #include #include #includ原创 2017-02-09 01:46:48 · 473 阅读 · 0 评论 -
Codeforces Round #388 (Div. 2)D. Leaving Auction(水题呀?)
题目链接:点击打开链接思路:我们只要把每个人竞价的最大值存起来, 并且把每个人的所有竞价维护在一个有序数组(方便二分), 对于一组询问, 我们从大到小遍历这k个数,把不在这k个数的最终竞价最大的两个人找到(复杂度O(K)), 然后在竞价最大的那个人的set里二分第二大的人的竞价最大值就行了。细节参见代码:#include #include #include #include原创 2016-12-20 22:02:50 · 937 阅读 · 0 评论 -
Codeforces Round #389 Technocup 2017 E. Santa Claus and Tangerines(二分+DP)
题目链接:点击打开链接思路:我们二分答案, 那么这就变成了一个二分求下界的问题了。 关于判定我采用了一种记忆化搜索的递归方式, 简单证明了一下应该可以达到log的复杂度。细节参见代码:#include #include #include #include #include #include #include #include #include #include原创 2016-12-25 21:07:07 · 694 阅读 · 0 评论 -
POJ 3237 Tree(树链剖分)
题目链接:点击打开链接思路:对于树上的路径更新操作, 我们通常把他hash到线段上, 也就是树链剖分, 大概完全理解了吧, 存个代码。对于该题的反转操作, 可以里用异或操作的性质来做标记。细节参见代码:#include #include #include #include #include #include #include #include #include原创 2016-12-08 21:20:17 · 429 阅读 · 0 评论 -
CDOJ 1292 卿学姐种花(分块)
题目链接:点击打开链接思路:由于是一个区间更新问题, 而且更新的值不一样, 所以我们考虑分块。 对于一个块, 我们维护第i块的第一个元素被加了多少了sum[i],第i块被更新了多少次cnt[i], 那么对于一个块内, 元素依次增加sum[i]递减cnt[i], 这是一个等差数列。细节参见代码:#include #include #include #include #inc原创 2016-12-06 17:53:16 · 706 阅读 · 0 评论 -
主席树
附上主席树代码, 以示我完全理解了主席树:#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define Max(a,b)原创 2016-12-05 21:01:29 · 566 阅读 · 0 评论 -
51 NOD 1521 一维战舰(并查集)
题目链接:点击打开链接思路: 倒着用并查集合并就行了, 一边合并一边统计, 当能放置的船数大于等于k就停止。细节参见代码:#include #include #include #include #include #include #include #include #include #include #include #include #include #原创 2016-11-28 22:48:52 · 638 阅读 · 0 评论 -
HDU 4366 Successor(分块)
题目链接:点击打开链接思路:把题目转化一下就是: 求一个区间内所有大于能力值v的人中忠诚度最大的是哪个人。我们考虑分块, 对于一个块内的人, 我们另开一个数组维护, 将块内的人按照能力值排序, 二分这个能力值, 之后还要维护一个左端点变化的区间最大值, 预处理即可。细节参见代码:#include #include #include #include #inclu原创 2016-11-11 12:29:17 · 590 阅读 · 0 评论 -
POJ 3622 Gourmet Grazers(set)
题目链接:点击打开链接思路:我们可以先排序, 先按照分数排序再按照价钱排序。 这样从前向后动态处理, 到了当前这头牛, 把商店里分数大于等于它需求的商品都加进去, 这样, 集合中所有的元素的分数都一定满足后面的, 所以分数这个因素就已经保证了。 然后set中按照价钱排序, 可以用二分快速找到价钱大于等于牛的需求的第一个产品。细节参见代码:#include #include原创 2016-09-08 12:54:00 · 501 阅读 · 0 评论 -
POJ 3109 Inner Vertices(线段树)
题目链接:点击打开链接思路:题目可以转化成这样的问题: 有多少个白点的上下左右都有黑点, 答案是这样的白点个数 + n怎么求符合要求的白点个数呢?按照常见思路, 我们先对黑点进行排序, 先按x再按y将其分层。 然后我们处理到了第i列, 符合要求的白点一定在相邻的上下两个黑点之间, 我们假设此时相邻两个黑点的y坐标是L和R, 那么我们要求区间[L+1, R-1]里有多少个白点的左右原创 2016-09-07 16:25:15 · 693 阅读 · 0 评论 -
Ural 1671. Anansi's Cobweb(并查集)
题目链接:点击打开链接思路:由于我们对删除边之后的状态很难处理, 我们可以考虑对询问倒着处理, 转化成对集合的合并问题。细节参见代码:#include #include #include #include #include #include #include #include #include #include #include #include #incl原创 2016-09-06 15:44:27 · 655 阅读 · 0 评论 -
UVA 10457 - Magic Car(并查集)
题目链接:点击打开链接思路:由于M只有1000, 我们可以从小到大枚举最小边, 用并查集维护连接情况, 当s和t连接时, 这时的边就是最大边。 复杂度O(m^2)细节参见代码:#include #include #include #include #include #include #include #include #include #include #inc原创 2016-09-05 16:26:01 · 1099 阅读 · 0 评论 -
UVA 1153 - Keep the Customer Satisfied(贪心)
题目链接:点击打开链接思路:我们按照时间从小到大排序, 因为时间最大2e6, 所以从小到大枚举时间, 当一个订单到了最后期限, 我们就看看它能否满足, 如果能就满足它, 如果不能, 我们看一下之前满足的订单中货物最多的一个是否比当前这个大, 如果大,就拿它换当前这个, 为后面节省空间。 用优先队列可以很方便的维护。细节参见代码:#include #include #inclu原创 2016-09-04 18:16:16 · 551 阅读 · 0 评论 -
HDU 5828 Rikka with Sequence(线段树)
题目链接:点击打开链接思路:对于该题, 由于存在区间加一个值, 那么所有数都可能永远不会变成1, 但是数与数之间的相对值会趋近于相等。 比如1 2 3 4 5, 进行一次根号操作变成1 1 1 2 2, 而一旦如果相等, 那么他们同时加一个数也是相等的。 所以我们增加一个标记bit[rt]表示该区间内的数是否全部相等,如果相等等于什么。细节参见代码:#include #inc原创 2016-08-11 20:39:37 · 1088 阅读 · 4 评论 -
SGU 507 Treediff(平衡树)
题目链接:点击打开链接思路:我们要求叶子结点的值相差最小, 那么这是一个大小关系, 我们可以维护一棵平衡树, 这样, 对于每一个数, 和他相差最小的情况只能是他相邻左边或右边。但是如果开n棵平衡树, 复杂度高达n^2logn,还不如n^2暴力来的快。 我们可以采用一种叫做: 启发式合并 的技巧。 每次将一棵比较小的树合并到一棵比较大的树上。 使得复杂度达到nlogn, 证明也很简单:考原创 2016-08-23 21:09:28 · 939 阅读 · 0 评论 -
Ural 1028. Stars(树状数组)
题目链接:点击打开链接思路:为了满足第一个条件, 我们可以先按照x坐标排序, 然后我们用树状数组来维护y坐标大小关系, 就可以在O(nlogn)的时间内求出答案了。细节参见代码:#include #include #include #include #include #include #include #include #include #include #i原创 2016-08-10 20:43:13 · 867 阅读 · 0 评论 -
UVA 10600 - ACM Contest and Blackout(最小生成树&次小生成树)
题目链接:点击打开链接题意:n个点,m条边,求最小生成树的值和次小生成树的值。思路:最小生成树就不说了, 如何求次小生成树:可以证明, 次小生成树一定是最小生成树加一条边然后减去一条边形成的。 所以只需要枚举减去最小生成树中的哪条边, 然后在此前提下再生成一遍最小生成树就行了, 复杂度O(n*m)。还有一种更好的方法:枚举要加入哪条新边, 在最小生成树上加入一条边u-v后,图上会出现原创 2016-02-15 21:24:06 · 2430 阅读 · 0 评论 -
UVA 11354 - Bond(并查集-按秩合并)
题目链接:点击打开链接题意:给出一张n个点m条边的无向图, 每条边有一个危险度,有q个询问, 每次给出两个点s、t,找一条路, 使得路径上的最大危险度最小。思路:首先,我们可以发现,如果求一个最小生成树, 那么任意两点, 在生成树上有唯一路径, 而且这条路径上的最大危险值一定最小。 但是n和q都太大, 如果直接顺着树走,每次询问最大复杂度O(n), 那么复杂度高达O(n^2),会超时。原创 2016-02-15 16:14:32 · 3518 阅读 · 0 评论 -
UVA 1494 - Qin Shi Huang's National Road System(次小生成树)
题目链接:点击打开链接题意:n个城市,需要修建一些道路使得任意两个城市联通,还可以修一条魔法道路, 不花钱, 设魔法路连接的城市的人口之和为A, 所有道路总长为B, 求A/B的最大值。思路: 次小生成树。 先做一次最小生成树, 然后用dfs搜索出最小生成树上任意两点之间最长的道路长度。 然后枚举在哪两个城市之间建魔法道路。n^2复杂度。细节参见代码:#include#inclu原创 2016-02-14 21:01:01 · 1616 阅读 · 0 评论 -
11987 - Almost Union-Find(并查集删除操作)
该题的难点就在于删除操作, 对于删除操作是有一个通用方法的 。 首先我们要明确,由于并查集是一个树状结构,内部关系复杂,所以如果将其中的一个点直接拆出来,势必会导致树状结构解体。 那么怎么办呢? 我们其实可以不必改变其原有结构,而是用一个id[i]数组表示元素i的编号,每次的删除操作即给元素i分配一个新的编号。因为要求输出集合的元素个数和他们的和,所以我们需要维护这个信息,因为并查集原创 2015-09-20 11:09:50 · 1385 阅读 · 0 评论