
ACM数据结构问题
HZ-VUW
这个作者很懒,什么都没留下…
展开
-
HDU 1896 优先队列
题意一人扔石头,遇到的第奇数个石头扔出去,偶数个石头走过去,如果同一位置遇到多个石头,扔的最近的最先遇到。问最远的石头能扔多远?题解优先队列水题,把石头扔到优先队列里就行了补充知识记录这道题主要是记录一下优先队列的使用方法,以及使用说明。 (刘汝佳的紫书P119页有优先队列的详细描述。) 优先队列的声明与自定义排序struct cmp{ bool operator()(Node a,No原创 2017-07-19 12:12:29 · 369 阅读 · 0 评论 -
CodeForces 86D 莫队算法
题意如果一个区间内有1个2和3个1,那么这个区间的值就是1*1*2+3*3*1。进行T次询问,每次询问输出区间的值。题解问一个区间内有多少个X,这明显就是莫队的套路。没有太多好说的,直接直接套用一下莫队算法就能AC。注意事项CF真的坑,加了IO挂依然TLE。最后把sqrt(n)改成了sqrt(n*1.0)。瞬间就AC了。原本以为这两个计算结果会有不同,然后试了一下,N从0-5000万都计算了一下,这原创 2017-09-06 14:01:58 · 299 阅读 · 0 评论 -
ZOJ 3195 LCA+RMQ+找规律
题意给三个点,求这三个点的相连最短距离。题解LCA+RMQ是模板,没什么好说的。规律的话,就是最短距离为dis[a]+dis[b]+dis[c]-dis[num[x1]]-dis[num[x2]]-dis[num[x3]]。画一下图就能发现这个规律对于所有的可能情况都是满足的。注意事项PE好几发,ORZ。。这种输入方式还搞Between Blank Line也是很有趣。。代码#include <io原创 2017-08-24 14:50:15 · 254 阅读 · 0 评论 -
Codeforces 863D 模拟
题意有一组数,可以进行两种变换,一种是区间元素循环右移,一种是区间元素翻转。最多有20万操作,最后有100次查询,问某个点的值是多少。题解看起来是一道很难的数据结构题,但是查询只有100次,所以暴力模拟就可以了。。。100次查询,逆着推,一直退到所有操作之前,输出这个值就可以了。代码#include<bits/stdc++.h>#define LL long long#define UP(i,l原创 2017-09-23 18:31:22 · 465 阅读 · 0 评论 -
HDU 5057 分块
题意有一组数,支持两种操作,修改和查询。每次查询可查询L到R这个区间内,第D位为P的元素有多少个。每次修改可修改一个点的值。题解纯分块,将元素分成256个元素为一块。使用num[i][j][k]代表第i块,第j位为k的元素有多少个。dig[i][j]代表第i个元素的第j位为多少。每次修改直接修改就可以了。每次查询对于l所在块和r所在块逐个遍历,对于中间块直接读取值就可以了。代码#include <i原创 2017-09-07 22:02:42 · 409 阅读 · 0 评论 -
POJ 2104 主席树
题意给一组数,问某个区间第K小的数题解主席树模板题,网上有很多关于主席树的讲解。主席树的话,我的理解就是类似于GIT的一种重复利用上一次结果的数据结构,很有意思。每插入一个点就建立一个线段树,这样的话可以大大提升线段树的能力,使得普通线段树具有部分平衡树的功能。当然,如果暴力去建的话,时间和空间都是不允许的,但是有神牛想出了主席树,大大简化了建树的时间和空间。节省时间和空间的方法是每次更新只更新真正原创 2017-08-30 22:45:09 · 235 阅读 · 0 评论 -
HDU 4622 莫队算法+逆元
题意有N个girl,一个人要去见这N个girl。这些girl分别在某个教室中。每次询问一个L和R,代表这个人要去访问第L到第R个girl,问访问教室的序列有多少种排序方式。题解区间L到R内有1号元素有num[1]个,N号元素有num[N]个,那么区间L到R的组合方式有(R-L+1)!/num[1]!* .. num[n]!种。(C(num[1],r-l+1) C(num[2],r-l+1) * .原创 2017-09-08 16:28:41 · 279 阅读 · 0 评论 -
HDU 6215 队列+链表
题意不断从一个序列中删除下降子序列,直到不出现下降子序列。题解纯链表很容易TLE,需要用队列进行优化。处理的思想是这样子的,如果我们删除了某个下降子序列,那么就有可能存在下降子序列的前一个元素与后面的一些元素组合成一个下降子序列。因此我们需要将前一个元素加入队列,再加入队列前需要将链表进行删除操作。同时由于删除了一些元素,对应的队列中也应该将这些元素POP掉。为了防止将刚加入的元素POP掉,我们需要原创 2017-09-18 08:42:37 · 953 阅读 · 0 评论 -
HYSBZ 2038 莫队算法
题意中文题,不解释题解莫队入门题。其实莫队就是暴力,只不过利用了上一次计算的结果,同时对区间进行合理分块,可以使得复杂度可以降低到O(N^(3/2))。题目要求求区间内任意选两个数,相同的概率。如果时间宽松一点,对于稍微有点数学基础的选手都可以在5分钟内写出相应代码,组合数公式随便搞一下就可以。 对于这道题就不行了,不但不能暴力,并且用什么数据结构都会感觉不舒服(会各种树套树的大牛可以无视此句。)原创 2017-09-02 23:13:01 · 284 阅读 · 0 评论 -
HihoCoder 1580 RMQ+DP
题意给一个矩阵,必须要修改一个值,使得最大子矩阵和最大。求这个最大子矩阵和。题解这道题非常坑的一点在于最大子矩阵并不一定要包含修改的元素,题目只是问了最大子矩阵而已。 由于这道题没有繁复的修改操作,但是存在最大值查询这一条件,我们首先考虑RMQ。可以发现这个最大子矩阵和的问题RMQ是无法解决的,于是我们考虑用DP去处理,用RMQ去进行优化。 首先我们去枚举子矩阵包含哪些行,这个是O(N^2)的,原创 2017-09-28 15:07:30 · 267 阅读 · 0 评论 -
HDU 6000 优先队列+快速IO
题意有L件衣服,N个洗衣机,M个甩干机,每个洗衣机和甩干机都有独立的处理时间,问洗完这些衣服最少需要多少时间。题解利用优先队列贪心地去做,也算是模拟吧,把衣服扔到洗衣机中,取出来加到一个数组中(加到队列中会超时)。然后倒着取出来这个数组中的元素(因为我们要保证洗衣机最后洗完的元素优先加到甩干机中,这样才能保证截止时间最短)。最后在所有衣服处理的截止时间中取最大值就可以了。代码#include<bit原创 2017-09-20 13:11:29 · 475 阅读 · 0 评论 -
HDU 4455 DP+树状数组
题意给一串数字,里面有N个数字。有Q次查询,每次查询长度为X的串,不相同的数字个数之和。题解很难看出来是DP,不过考虑到查询问题,并且无法用普通的数据结构进行解决,同时长度之间存在利用关系,因此可以用DP解决。 首先对于长度为1的串,很明显可以得到dp[1]=n。对于长度为2的串,我们首先要删除末尾的一个长度为1的串,然后对于每个串再加上一个值,如果新增了一个数字,那么这个值就是1,否则就是0。然原创 2017-10-08 00:34:53 · 639 阅读 · 0 评论 -
Gym 101161E 主席树+LCA
题意给一棵树,问树上路径权值中位数。题解树上路径权值中位数就是求第k/2大数,很明显主席树+LCA。这道题还是比较容易的,有一点非常重要的是权值W的范围是1-100000,这个范围很大程度上影响了题目的实现难度。由于权值最大只有10万,因此我们可以搞一个10万的主席树,这样的话每一次查询第K大,我们可以利用主席树去针对某一段版本的线段树去查询,从右到左的第K的数字就是第K大。 搞明白了这个,还有一原创 2017-10-19 22:19:31 · 297 阅读 · 0 评论 -
POJ 1986 RMQ+LCA
题意给一堆点,一堆边,问一个点到另一个点的最短距离。题解其实就是LCA的模板题,只不过题目好坑啊,数据范围在1984这道题里,看错了数据范围,然后一直RE。代码#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queu原创 2017-08-23 22:02:05 · 264 阅读 · 0 评论 -
HDU 3486 RMQ+二分
题意给一组数,分成M组,每一组的人数为n/m,剩下的人丢弃。每组取最大的数,问要得到严格大于某个数的总和,最少需要分多少组题解这种题分组题,很容易便能想到是二分。只是注意一些边界情况就可以了,比如说选取的组位置边界。注意事项处理问题不要刻意追求巧妙,选择最稳妥的方式在大多数时候反而会更好。代码#include <iostream>#include<cstdio>#include<algorith原创 2017-08-23 16:08:40 · 221 阅读 · 0 评论 -
HDU 5726 RMQ+二分
题意给一堆数,问任意一段区间的GCD。并且求出有多少个区间和这个区间的GCD相等。题解求区间的GCD很好求,把模板套上去就可以了。至于多少个区间的GCD相等,暴力肯定是不行的,那样的话,ST算法就失去意义了。因为长区间的GCD一定小于或等于短区间的GCD,因此可以二分求取。 对于i<=j<=k,必然存在一段区间使得gcd(i,j)==gcd(i,k)。因为gcd(i,j)>=gcd(i,k)恒成立原创 2017-08-23 12:48:57 · 247 阅读 · 0 评论 -
POJ 2010 优先队列
题意有C头牛,选M头牛,每一头牛的分数是第一个数字,花费金钱是第二个数字。有F金钱。问如何选择可以使分数的中位数最大。题解网上的二分代码即便AC了,很多想法都还是有问题的。感觉正解应该是用优先队列,先将M头牛按成绩排序,设置两个数组l和r,l数组代表某头牛左边如果要选足够的牛(m/2头牛),所需要的最小花费,r同理。利用优先队列进行初始化。然后对于存在l和r的区间进行一遍遍历即可。代码#includ原创 2017-07-23 17:00:37 · 289 阅读 · 0 评论 -
HDU 4614 线段树(区间更新)+二分
题意有0-N-1个花瓶,两种操作。一种操作是从某个点开始,放F朵花,如果一朵花都不能放,则输出“Can not put any one.”,否则输出放花的区间。另一种操作是清理A到B区间内的所有花,输出清理的数量。题解感觉这道题还是有一些难度的,主要是要对题意有着比较深刻的理解。题目最坑的地方在于,可以放0朵花。更坑的是,放0朵花的话,比如在X点放0朵花,那么X点就会变成没有花的点。。。因此更新的时原创 2017-08-07 22:36:04 · 320 阅读 · 0 评论 -
POJ 2528 线段树+离散化
题意有N张海报,按顺序贴,问最后能看见多少张海报。题解题目中给的海报区间范围是0-10000000.这个数据量直接上线段树肯定是不行的,需要进行离散化处理。我选择了最丑陋的一种离散化方式,直接开了个10000000的数组,由于最多只有10000张海报,所以离散化映射过去最多20000个点。这样的话,问题就变成了一个区间修改,单点查询的问题。直接线段树模板解决。注意事项看了一下POJ的评论区,有很多人原创 2017-08-01 11:01:03 · 263 阅读 · 0 评论 -
HDU 4006 第K大元素(小技巧)
题意输入一些数,进行多次查询。每次查询都是查询第K大元素是什么。题解这道题考察的是堆(优先队列)的应用。。。。核心代码10行,主要是考察思想额外的尝试c++ STL 有个nth-element,利用类似快排的思想,查找第N个小的数,并把比他小的放在前面,比他大的放在后面(随机顺序)。很可惜,这种算法效率还不够高,TLE。。。代码#include <iostream>#include<cstdio>原创 2017-07-19 22:17:31 · 306 阅读 · 0 评论 -
POJ 1177 线段树+扫描线
题意给一堆正方形,问组合图形周长题解首先可以做扫描线入门题HDU 1542。了解了扫描线的原理之后,这道题其实就非常简单了。尤其是POJ还没有判重边。 可以直接用最粗暴的方式,横向扫描一次,纵向扫描一次。每次扫描,判断相比上一次宽度(长度)变化了多少,周长就加多少。扫描两次以后,周长即为所求。注意事项有个地方感觉很玄学,但是也很重要。离散化数组要开4倍,目前还尚不清楚原因,ORZ。。。代码#inc原创 2017-08-08 11:12:47 · 327 阅读 · 0 评论 -
HDU 1255 线段树+扫描线
题意中文题,不解释题解开始的时候,考虑用各种pushdown和maintain来维护扫描线信息,但是一直无法实现。看了题解才意识到,其实完全没有必要pushdown。(事实上,pushdown这种操作对于RMQ以及区间和问题是十分有效的,但对于扫描线维护这种问题是无效的。普通的线段树问题,是自顶向下的,顶端的setv或add会决定子节点query()的结果。但是扫描线维护是自底向上的,底部子节点的s原创 2017-08-08 19:33:37 · 284 阅读 · 0 评论 -
HDU 4553 线段树连续区间
题意中文题,不解释题解线段树真的是一题一世界啊。。刚开始的时候想到的并不是连续区间。以前有一道题也是找位置,修改点,但是允许非连续区间。那道题用的是二分。这道题原本也想用二分,但是一方面实现起来比较困难,另一方面即便真的实现了,在时间复杂度上也存在很大的问题。 因为必须要找一块连续的区间去做事情,所以说这道题完全不需要二分去找起始和终止位置。只需要维护连续区间长度就可以了,如果连续区间长度小于需要原创 2017-08-08 22:47:54 · 313 阅读 · 0 评论 -
ZOJ 1610 线段树
题意N次涂颜料,第I次涂x1到x2区间,涂颜色C。问最后能看见多少种颜色,以及这些颜色的连续块个数。题解单点查询,多点更新的线段树。由于数据范围只有0-8000,所以也不用做什么处理,随便搞搞就可以了。注意事项题目都错了然后就各种SF和WA。。。题目的意思是涂N次颜料,每次区间都在0-8000之间,而不是0-N之间。代码#include <iostream>#include<cstdio>#in原创 2017-08-04 10:56:10 · 288 阅读 · 0 评论 -
HDU 4027 线段树
题意N个点,每次攻击或查询一个区间,攻击区间可以使区间内的所有点的生命值变为sqrt(生命值)。查询一个区间,则输出该区间内所有生命值的和。题解这道题最重要的是剪枝。如果一个数为1后,开平方就无效,因此对于为1的区间,就直接跳过,不进行开平方处理,这样可以大大节省时间。有个比较坑的事情是数据没有0,这样的话直接利用一个和数组就可以判断该区间内所有的数字是否为1。(更坑的是,如果单独开一个数组来判断区原创 2017-08-04 20:31:16 · 211 阅读 · 0 评论 -
HDU 1540 线段树(区间查询)
题意有N个点,每两个点之间存在一条通路,D x代表摧毁x点,R代表修复最近摧毁的一个点。Q x代表查询x点能连接多少个村庄(包括自己)。题解比较复杂的线段树。状态需要用结构体保存。 l,r代表左边界和右边界,ls代表左连续区间长度,rs代表右连续区间长度。ms代表区间内最大连续长度。注意事项原创 2017-08-05 08:37:22 · 298 阅读 · 0 评论 -
POJ 3321 树状数组+DFS
题意给一棵树,输入C和一个点的话,如果这个点上原来有苹果的话,则这个点将会变成没有苹果的点。如果这个点上原来没有苹果的话,则这个点将会变成有苹果的点。如果输入Q的话,则代表进行查询操作,查询操作是查询某个点及其子树的苹果总和。题解树状数组+DFS序。这个就和线段树是一样的。首先的话,DFS序给所有点编号。点更新的话,直接单点更新就可以了。查询的话,找到查询点的起始和终止编号,利用树状数组进行区间查询原创 2017-08-19 18:57:28 · 227 阅读 · 0 评论 -
FZU 2277 线段树+DFS序
题意对一棵树进行操作,1 v x k代表对根节点v加x,对v的子节点加x-k,对孙子节点加v-2k。2 v代表查询节点V的值。题解其实是一个很简单的线段树,对于一次增加操作,节点x增加的值其实就是x-(deep[x]-deep[v])*k。(deep[v]为该次修改的根节点)。查询的时候单点查询,也不用pushdown,直接再递归返回的时候加上中间节点的值就可以了。注意事项需要求DFS序,需要特别注原创 2017-08-07 09:41:22 · 581 阅读 · 0 评论 -
HDU 6058 链表
题意给一组数,这一组数包含很多个子序列,求这些子序列第K大元素的和。题解观察发现K很小,因此可以从此着手。 首先我们可以观察一下2,3,4,1,5(求第2大的和)这个序列的计算情况 我们可以发现,4出现了三次。因为右边有一个5,如果子序列包含这一个5,然后左边没有比4大的数的时候,4是第2大的数,也就是符合情况的数。这时候,左边有三种情况符合这种条件,即左边没有元素,左边有3,左边有2,3。原创 2017-11-04 20:17:35 · 380 阅读 · 0 评论