数据结构
leohujx
这个作者很懒,什么都没留下…
展开
-
Aoj 2170
简单的并查集应用。 不过注意,我们平常用的路径压缩在这里就不能用了,因为我们并不更新路上的所有结点到同一个并查集中去,这里只是做查询的用途。 题目中当mark一个点时,我们就用fa[x]=x去更新某个点,使它作为一个并查集的根节点,然后如果要查询离x最近的mark点,那么我们就逐渐网上找,找到第一个fa[x]=x的点,然后返回它的值,注意,这过程中我们不能进行路径压缩。#include<stdi原创 2015-09-29 14:09:48 · 513 阅读 · 0 评论 -
poj 2010
这道题目之前好像差不多做过一次,所以比较有思路。我们先将所有的值按照score从小到大排序,然后用优先队列(按照financial大的在前)维护某个数前面和后面各前n/2个最小的数,sum1[i]代表i前面n/2个最小的finacial之和,sum2[i]代表i后面n/2个最小的financial之和。最后从后往前遍历一遍,找到一个sum1[i]+sum2[i]+a[i].financial<=f的原创 2015-10-12 15:46:10 · 352 阅读 · 0 评论 -
poj3368
RMQ求区间最大值。 要求某一段区间内出现的最多的数字的次数。那么我们用一个f[i]来记录某个位置上出现的连续数字个数。然后用RMQ处理,在处理左边界的时候,我们要注意排除一段连续的相同数字,因为我们记录f[i]的时候就是做的前缀和,排除后做新区间的RMQ,然后再与排除的那一段区间大小进行比较。#include<stdio.h>#include<iostream>#include<string原创 2015-11-11 17:50:24 · 424 阅读 · 0 评论 -
poj3264
区间求最大最小值问题,可以用RMQ算法。#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<algorithm>#include<iomanip>#include<vector>#include<time.h>#include<queue>#include<stack>#inc原创 2015-11-11 13:53:23 · 317 阅读 · 0 评论 -
poj2886
线段树+反素数。这题是类似于约瑟夫环的问题。 首先我们得了解反素数,我们有n 个人,那么就至少有n个回合,要求第几个出局的人获得的糖果最多(获得的糖果数等于第i轮出局的人,i所含的因子的个数),而反素数的定义就是对于一个数字x,有任意一个i(0< i < x),都有g(x)>g(i) (g(x)代表x所含的因子的个数),所以对于1-n来说,含有因子的数目最多,又得是最多里面数字最小的,那么只有那个原创 2015-11-10 20:31:43 · 756 阅读 · 0 评论 -
poj2155
二维树状数组。记录一个矩阵中的某个位置被提到几次,有篇文章说的很好。imos 至于怎么高效改变一个区间的值,高效询问某个位置的值,那么用树状数组是最快的。#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<algorithm>#include<iomanip>#include<vec原创 2015-11-09 19:44:49 · 301 阅读 · 0 评论 -
poj1990
题目意思就是有m头牛,每头牛有两个值,v和x,两两之间有一个值,设v分别为v1,v2,x为x1,x2,则它们之间的值为abs(x1-x2)Max(v1,v2),求所有m(m-1)/2对牛之间值的总和。 暴力的话很好理解了,但是这里的m数据范围最大为20000,n^2的效率是不可取的。所以这里我们引入树状数组。这道题目我们得用两个两个树状数组,一个叫做num[x],可以计算小于坐标x的坐标有几个,另原创 2015-11-09 16:15:07 · 1167 阅读 · 0 评论 -
poj 3614
优先队列求解。 将防晒霜按值从小到大排序,将蚂蚁的最小忍耐值按从小到大排序,然后对于每个防晒霜,如果该蚂蚁的最小忍耐值小于等于它的值,那么就把该蚂蚁的最大忍耐值放入优先队列,该优先队列的规则是将小的数放前面,也就是我们取那个最小且符合题意的忍耐值。#include<stdio.h>#include<iostream>#include<string>#include<string.h>#in原创 2015-09-16 21:59:05 · 357 阅读 · 0 评论 -
poj 2236
并查集应用的简单题。对于每一个修好的电脑,我们遍历所有已经修好的电脑,如果它们之间的距离小于等于d,那么我们就将两个集合合并到一起,在询问是否能够互通时,就看它们是否属于同一个集合,但是我们不能写成fa[x] == fa[y],而应该写成find(x)==find(y),因为有可能有些节点并没有进行路径压缩,进而也没有在同一个集合中,所以我们得再压缩一下。#include<stdio.h>#inc原创 2015-09-17 18:25:59 · 302 阅读 · 0 评论 -
poj 1703
经典的并查集问题。 我们可以有两种做法: 第一种是我们用一个数组vis[i]=j来表示i的敌人是j,那么我们在知道a,b是敌人之后,那么如果vis[a]有值的话,vis[a]和b是一伙的,如果vis[b]的有值的话,vis[b]和a是一伙的。所以这样判断即可。#include<stdio.h>#include<iostream>#include<string>#include<string原创 2015-09-17 19:14:06 · 277 阅读 · 0 评论 -
poj 2010
这道题目刚开始还真不好想,看了别人的解题思路之后恍然大悟,思路太棒了~ 题目大意是给你三个值,N,C,F,C代表有C头牛,N为奇数,代表要在C头牛中选择N头牛,每头牛有两个值,分数和代价,使得被选中的N头牛的中位数尽量大,并且它们的代价和不能超过C。 刚开始将所有的牛按照分数大小排序,然后我们用lower[i]来表示前i头牛中(不包括第i头牛)代价和最小的N/2头牛的总代价和,那么我们从头开始扫原创 2015-09-17 10:22:12 · 370 阅读 · 0 评论 -
hdu 5441
这道题目是用并查集来维护联通点的个数。 我们首先将所有路径按权值大小从小到大排序,然后将所有询问也按权值从小到大排序(没错,我们要离线处理),接着遍历一遍询问,将符合条件的路径两端点合并,我们用rk[i]来代表i点所在并查集的大小,假设两个端点分别为u,v,那么它们所在并查集大小为rk[u],rk[v],则当这两个点合并以后,这两个并查集中的点就合并起来了,根据题意,多出来的数目为rk[u]*rk原创 2015-09-14 21:44:10 · 369 阅读 · 0 评论 -
poj 5444
这题。。其实我对树这玩意还是有点恐惧的。。(:зゝ∠) 直接模拟不就好了!#include<stdio.h>#include<iostream>#include<string>#include<string.h>#include<algorithm>#include<iomanip>#include<vector>#include<time.h>#include<queue>#i原创 2015-09-14 22:25:26 · 289 阅读 · 0 评论 -
hdu 5536
当时在现场做的时候队友写了个超级麻烦的,知道肯定不这样做,但是当时是在想不出另外的做法,后来知道原来O(n^3)也能过。。ORZ正解是用字典树,先把所有数字的二进制表示存入字典树,然后枚举i和j,从字典树中删除i和j代表的数字,接着开始反向匹配,如果a[i]+a[j]代表数字的二进制的那一位是0,则我们就匹配字典树中相应地方是否有为1的,反之则反。这样一来我们就能匹配最大的结果。匹配结束后及时把i原创 2015-11-02 11:46:17 · 740 阅读 · 4 评论