随笔分类 -  数据结构

摘要:DLX用于优化精确覆盖问题,由于普通的DFS暴力搜索会超时,DLX是一个很强有力的优化手段,其实DLX的原理很简单,就是利用十字链表的快速删除和恢复特点,在DFS时删除一些行和列以减小查找规模,使得搜索深度越深而越小,然后回溯继续查找。具体资料可【点击这里】。 精确覆盖问题(补充):具体一点儿就是给你一个0-1矩阵,要你找出一些行,使得每一列都有且只有一个1。HUST 1017Exact cover 入门必做,测试模板。 1 #include 2 #include 3 4 const int N = 1005; 5 const int M = 1000005; 6 c... 阅读全文
posted @ 2013-10-18 15:00 芒果布丁 阅读(319) 评论(0) 推荐(0)
摘要:今天遇到一道海量数据处理方面的题,题目是这样的: 100w个数中找出最小的100个数。 那么题目稍微抽象出来就是这样的:在N个数中找出前n小的数。这种题有一个特点:N很大,n很小。那么,我们就可以利用最大堆在O(Nlogn)的时间复杂度内得出答案。 最大堆的数据结构模型不再赘述,可自行参照百科。 用最大堆解决上述问题的步骤是这样的: 1. 建空二叉堆,其大小为100(可以用链表方式的堆,但是本人更倾向于数组型的堆); 2. 对于原数据的前n个数,按照最大堆堆顶元素大于左右儿子的特性直接构造最大堆; 3. 对于后续元素v,如果v大于堆顶元素,则用v替换掉堆顶元素,... 阅读全文
posted @ 2013-04-16 19:45 芒果布丁 阅读(258) 评论(0) 推荐(0)
摘要:原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=4417 划分树 + 二分。 总复杂度为mlog(n)log(n),在O(10^7)左右,可以破了,二分查询区间第k大值,如果该值小于或等于给定高度,那么继续二分。那么最后得到的k值就是所求。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 const int maxn = 100000 + 10; 5 6 int tree[20][maxn], num[20] 阅读全文
posted @ 2012-11-22 19:32 芒果布丁 阅读(153) 评论(0) 推荐(0)
摘要:原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=3473 做出这题感觉又帅了。 划分树。 一看题目很容易想到每次查询求的x就是该区间排序后的中位数,再看看规模,不难想出得用划分树nlog(n)。 尽管题目给了8s的时限,然而,如果每次只是求出中位数在循环一遍区间去求答案,也会TLE,所以,另开数组lsum[],在建树的时候记录放到左子树的元素的和,则可在每次询问的时候,如果在树的某一层要进入右子树,那么,该区间进入左子树的所有元素的和都是小于中位数的。 另外,如果这题写丑了会卡掉内存的,当时我写的时候是开两个数组lsum[]和rsum... 阅读全文
posted @ 2012-11-22 18:40 芒果布丁 阅读(184) 评论(0) 推荐(0)
摘要:【原题链接】 约瑟夫环,普通链表法O(nk)复杂度无法承受,但是可以有O(n)的算法。 以下摘自百度百科: 无论是用链表实现还是用数组实现都有一个共同点:要模拟整个游戏过程,不仅程序写起来比较烦,而且时间复杂度高达O(nm),当n,m非常大(例如上百万,上千万)的时候,几乎是没有办法在短时间内出结果的。我们注意到原问题仅仅是要求出最后的胜利者的序号,而不是要读者模拟整个过程。因此如果要追求效率,就要打破常规,实施一点数学策略。 为了讨论方便,先把问题稍微改变一下,并不影响原意: 问题描述:n个人(编号0~(n-1)),从0开始报数,报到m-1的退出,剩下的人继续从0开始报数。求胜... 阅读全文
posted @ 2012-11-12 15:07 芒果布丁 阅读(279) 评论(1) 推荐(0)
摘要:原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=3474 单调队列。 这题的模型可以这样描述:给一个只由1和-1组成的循环序列,求以每个点为起点且长度最长为n的子串的最小值。到这一步,应该能想到单调队列的解法了。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define N 2000005 5 6 int sum[N], a[N], q[N], n, ok1[N], ok2[N]; 7 8 void c 阅读全文
posted @ 2012-10-17 21:04 芒果布丁 阅读(249) 评论(0) 推荐(0)
摘要:原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=3415 【题目分析】 因为序列是环状的,所以可以在序列后面复制一段(或者复制前 k 个数字)。如果用 s[i]来表示复制过后的序列的前 i 个数的和,那么任意一个子序列[i..j]的和就等于[j]-s[i-1]。对于每一个 j,用 s[j]减去最小的一个 s[i](i>=j-k+1)就可以得到以 j 为终点长度不大于 k 的和最大的序列了。将原问题转化为这样一个问题后,就可以用单调队列解决了。View Code 1 #include <stdio.h> 2 #include < 阅读全文
posted @ 2012-10-17 17:48 芒果布丁 阅读(203) 评论(0) 推荐(0)
摘要:原题传送:http://poj.org/problem?id=2823 单调队列练手题。(不怕麻烦也可以用线段树) 程序运行了5000+ms,不明白几百ms的是什么算法,如果读者您知道请留个言,感激不尽。View Code 1 #include <stdio.h> 2 #include <string.h> 3 #define N 1000005 4 int a[N]; 5 6 struct node 7 { 8 int key, val; 9 }e[1000005];10 11 12 int main()13 {14 int n, k, i, head, tail.. 阅读全文
posted @ 2012-10-17 12:44 芒果布丁 阅读(165) 评论(0) 推荐(0)
摘要:原题传送:http://poj.org/problem?id=2513 字典树 + 并查集 + 欧拉路。 字典树:相当于hash的功能 并查集:判断连通 欧拉路:求答案 要存在欧拉路就要满足: 1.该图必须是一个连通图 2.该图每个点的度数要么全为偶数,要么有且仅有两个点的度数为奇数View Code 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 500005 5 using namespace std; 6 7 int k, f[N],g[N]; 8 ch 阅读全文
posted @ 2012-10-15 10:58 芒果布丁 阅读(165) 评论(0) 推荐(0)
摘要:原题传送:http://poj.org/problem?id=2418 用的是STL神器,map + priority_queue。(C++提交和G++提交相差6s !)View Code 1 #include <map> 2 #include <queue> 3 #include <string> 4 #include <iostream> 5 #include <iterator> 6 #include <stdio.h> 7 using namespace std; 8 9 typedef pair<strin 阅读全文
posted @ 2012-09-15 10:18 芒果布丁 阅读(182) 评论(0) 推荐(0)