随笔分类 -  Algorithm

摘要:这道题,已知一个数组a,a[i]排好序后位于a[i-k]跟a[i+k]之间,问说该怎么最快地排序。可以转换成多路归并问题,a[0]<a[k+1]<a[2k+2]<a[3k+3]...a[1]<a[k+2]<a[2k+3]<a[3k+4]......a[k]<a[k+(k+1)]<a[2k+(k+2)]<a[3k+(k+3)]...多路归并后的算法复杂度是O(nlogk)。 阅读全文
posted @ 2013-09-26 10:17 litstrong 阅读(323) 评论(0) 推荐(0) 编辑
摘要:注意到单词的长度最长100,其实最糟糕复杂度应该能到O(300005*100),需要注意的是在字典树上匹配单词时,一旦不匹配,则后面的就不会匹配,需要break出来(这个害我TLE查了半天,日!),还有,要注意strlen的时候,那个api的复杂度貌似是O(n)的,题目中提到输入数据的不同的test case之间有一个blank line,我理解成输出不同case之间要回车,OJ居然没判成PE,而是判成WA,这两天题写的真蛋疼(吐槽下)。#include #include #include #include #include using namespace std;const int MAXN 阅读全文
posted @ 2013-09-05 10:47 litstrong 阅读(223) 评论(0) 推荐(0) 编辑
摘要:1. 每次找剩下序列中的最大值,可以进行pancake sort,时间复杂度是O(n^2);2. 求最少交换次数进行pancake sort的问题是个NP问题,搜索的时候,upper bound是2(n-1)次,而lowwer bound(即至少需要的步数)是剩下的序列中相邻两个元素不是排好序的个数,根据上面的两个bound可以进行剪纸,也可以考虑寻找状态重复情况,不过当n比较大时,就没有办法记录了吧;3. 若Flip的复杂度是O(1),则可以使用插入排序的算法,遍历序列中的元素,然后在排好序的序列中二分查找后,通过几次Flip操作将序列调整成有序的,复杂度是O(nlgn)。 阅读全文
posted @ 2013-09-04 17:17 litstrong 阅读(425) 评论(0) 推荐(0) 编辑
摘要:B.Maximal Area Quadrilateral题意:在N个点中构建四边形,使得四边形面积最大,且不自交。分析:不自交四边形可以剖分成两个三角形,因此可以在O(N^2)内枚举对角线,然后用O(N)寻找离对角线最远的两侧的点。其实这题最快应该能到O(NlgN),求出点集的凸包,然后在凸包上转一下。C.Tourist Problem题意:统计N!种路线的距离的均值。分析:统计每段出现的次数,即统计(i,j)出现的次数,即统计(i_small, j_large)满足i_small<=i且j<=j_large下,出现的次数。D.Bubble Sort Graph题意:给定一个序列a 阅读全文
posted @ 2013-09-03 23:22 litstrong 阅读(216) 评论(0) 推荐(0) 编辑
摘要:A Simple Problem with Integers每次将区间向下更新,或是用之前的方法,统计当前节点到父节点处的覆盖数目。#include #include using namespace std;const int MAXN = 100005;typedef long long int64;int d[MAXN];class SegNode {public: int L, R; int64 c, sum; int64 get_c() { return c * (R - L + 1); } void log(const char *info) { ... 阅读全文
posted @ 2013-09-03 23:06 litstrong 阅读(144) 评论(0) 推荐(0) 编辑
摘要:哈哈,原来题意看错了,但有多个解的时候,输出起点靠前的,如果起点一样,则输出终点靠前的,修改后AC的代码如下:#include #include #include using namespace std;const int MAXN = 500005;typedef long long int64;int dish[MAXN];int64 dish_sum[MAXN];int64 get_sum(int L, int R) { return dish_sum[R] - dish_sum[L - 1];}class SegNode {public: int L, R; int ... 阅读全文
posted @ 2013-08-31 14:05 litstrong 阅读(266) 评论(0) 推荐(0) 编辑
摘要:今天无意间找到了训练指南的网上代码,都是刘汝佳写的,在这。今天在做这题1400-"Ray, Pass me the dishes!",我写的线段树的思路跟上次的Frequent Sequence的思路类似,维护区间上从左端点开始、从右端点开始,中间部分的最优序列,查了半天,没查到问题,先把代码备份上来。#include #include #include using namespace std;const int MAXN = 500005;typedef long long int64;int dish[MAXN];int64 dish_sum[MAXN];int64 g 阅读全文
posted @ 2013-08-29 15:50 litstrong 阅读(206) 评论(0) 推荐(0) 编辑
摘要:250:给一个串S,可以做这样的操作,可以将串中的一种字母变成另一种字母,代价是该种字母的数量。求解的问题是,最小的代价将串S变成回文串。根据回文关系,我们可以形成等价对应关系,a与b等价对应说明a和b必须是同种字母,根据这个关系,我们可以得到一个图,每个连通块表示要变成一种相同的字母,而这个操作的最小代价就是将连通块中除出现次数最多的字母全部都转变成出现次数最多的字母。#include #include #include #include using namespace std;bool mm[256][256];int cnt[256];bool used[256];class Goose 阅读全文
posted @ 2013-08-28 20:33 litstrong 阅读(341) 评论(0) 推荐(0) 编辑
摘要:250:有n首歌每首歌有duration和tone,连续唱m首歌会消耗每首歌的duration以及相邻两首歌的tone的差的绝对值的和,给个T,问说在T时间内最对能唱多少歌。将歌按tone排序后发现,只要枚举连续歌的最左和最右,这样产生的收尾的tone的绝对值的差的和是不变的,然后将中间的歌按duration从小到大唱,知道时间T消耗完毕。500:要发现访问若干room后获取到的钥匙的数量与访问的顺序是无关的,用dp(i, j)表示访问过i(i表示访问过的room的二进制状态压缩)后,手里拥有j把红钥匙的白钥匙最多的数量。#include #include #include #include 阅读全文
posted @ 2013-08-28 20:22 litstrong 阅读(207) 评论(0) 推荐(0) 编辑
摘要:12232-Exclusive-OR题目大意是可以设定一个点Xp=v,或者Xp^Xq=v,然后查询Xa^Xb^Xc...等于多少。由于异或操作跟判连通性很类似,这里可以使用并查集来解决,对于Xp^Xq=v先判断Xp和Xq是否来自一颗树,若是来自一个棵树,则判相容性,否则连接这两棵树,而Xp=v是用来lock一棵树的,当一棵树未被lock时,这颗树中的所有值都不确定,当lock之后,就可以确定这颗树的所有值了。而最后求Xa^Xb^Xc...时,先按树进行分类,对于lock的树的X直接求解,都与非lock的树,若有偶数个则可以求解,否则得不到固定的值,算法应该没有问题,可是AC不了,不好debug 阅读全文
posted @ 2013-08-27 16:04 litstrong 阅读(359) 评论(0) 推荐(0) 编辑
摘要:11988-Broken Keyboard (a.k.a. Beiju Text)可以用deque来模拟。#include #include #include #include #include using namespace std;const int MAX = 100005;char ch[MAX];int main() { while (scanf("%s", ch) != EOF) { deque Q; string buffer = ""; int toward = 1; int n = strlen(ch); ... 阅读全文
posted @ 2013-08-27 15:57 litstrong 阅读(311) 评论(0) 推荐(0) 编辑
摘要:C. Xenia and Weights有1...10k的砝码,在天枰上,左右轮流放置砝码,要求之后左右轮流比另一侧重量要大,要求相邻两次砝码不能相同。解题报告给出(i,j,k)表示balance,j表示最后一次的砝码重量,k表示第几步,然后表示从点(0,0,0)->(x,y,m)的图论问题,跟动态规划是等价的,复杂度是O(w^3*m)。我给出了一个比上述算法更优的一个算法,做法是用dp[i][j]表示第i步balance达到j时的所有可能的砝码情况的二进制mask,复杂度是O(w^2*m),但要求w#include #include #include using namespace s 阅读全文
posted @ 2013-08-27 15:43 litstrong 阅读(4350) 评论(0) 推荐(0) 编辑
摘要:早早得就学了线段树的一些基础应用,当时急于应用,对它的好多认识都比较肤浅,最近拿起来复习了下,加深了些对它的理解。我觉得重要的就是要理解,对于一条线段[L R]在线段树中插入或是更新或是查询,它的复杂度为什么是log级别的,我想了两个方法来证明:1. 对于线段[L R]对node[r].L及node[r].R的覆盖情况,可以分成三种情况,一种是node[r].L及node[r].R被线段[L R]覆盖;一种是node[r].L及node[r].R其中一个端点被[L R]覆盖;最后一种是两个端点都不被覆盖。第一种就直接返回了,第二种到下一层节点的时候,又转变成了第二种的问题,因此复杂度最高是树高 阅读全文
posted @ 2013-08-27 15:25 litstrong 阅读(201) 评论(0) 推荐(0) 编辑
摘要:Hoax or what题意是询问一个动态序列的最小值和最大值。可以用multiset来实现。#include #include using namespace std;int main() { freopen("h.in", "r", stdin); freopen("h.ans", "w", stdout); int n; while (scanf("%d", &n) && n) { multiset bills; int sum = 0; for (int i = 阅读全文
posted @ 2013-08-26 17:21 litstrong 阅读(289) 评论(0) 推荐(0) 编辑
摘要:Frequent values题意是不同颜色区间首尾相接,询问一个区间内同色区间的最长长度。网上流行的做法,包括翻出来之前POJ的代码也是RMQ做法,对于序列上的每个数,记录该数向左和向右延续的最远位置,那么对于一个查询Q(L, R),它的答案就分成了三种情况right(L) - L,R - left(R)以及Q(L+right(L),R-left(R))。这里给出一个线段树做法,在线段树的节点上维护3个量:l_value, r_value, value分别表示以左端点为起始点,以右端点为起始点以及该区间内的最大的连续长度,更新时通过两个子区间相接的地方是否相同分不同的情况进行讨论。#incl 阅读全文
posted @ 2013-08-26 11:16 litstrong 阅读(359) 评论(0) 推荐(0) 编辑
摘要:Book of Evil,有一颗树,n个节点,有m个节点被标记,问n个节点中,有多少个节点,这些节点与这m个节点的最远的距离小于等于d。用down[i], up[i]分别标记只考虑以i为root的子树的情况与这颗补集并上节点i的情况,两遍dfs,第一遍dfs求出down数组,第二遍求up数组,求up时,需要考虑当前节点i的父亲节点的up值以及节点i的兄弟节点的down值,然后取最大值。在求兄弟们的最大值时,由于所有的兄弟都会有这样的操作,因此可以先求出最大和次大,如果当前节点i的down值不是最大的,那么最大的一定在兄弟中,否则次大的一定是兄弟中最大的。PS: 还个算法,可以先求出树中离得最远 阅读全文
posted @ 2013-08-17 19:41 litstrong 阅读(602) 评论(0) 推荐(0) 编辑
摘要:最近在复习数据结构,发现这套题不错,题目质量好,覆盖广,Data Structures部分包括Example,以及简单,中等,难三个部分,这几天把Example的做完了,摘要如下:通过这几题让我复习和练习了优先队列,并查集,并查集的路径压缩。总结如下:11995-I Can Guess the Data Structure!给出push,pop操作对应的序列,判定是stack, queue还是deque。用上面三个数据结构对应模拟下push,pop的操作,将结果与输出进行比对,需要注意的是如果pop一个空的数据结构时,以上三者就都不是了。#include #include #include # 阅读全文
posted @ 2013-08-16 11:59 litstrong 阅读(302) 评论(0) 推荐(0) 编辑
摘要:多少个平方数小于等于X,二分。PS:java BigInteger。import java.util.*;import java.math.*;public class Solution { public static void main(String args[]) { Scanner in = new Scanner(System.in); BigInteger X = in.nextBigInteger(); BigInteger L = BigInteger.valueOf(1); BigInteger R = BigInt... 阅读全文
posted @ 2013-08-12 12:35 litstrong 阅读(161) 评论(0) 推荐(0) 编辑
摘要:SGU128,题意是给定N个点,问说能不能形成一个闭环G,要求G经过每个点,且在每个点处都有90度的转角,且不能出现自交。没想出来,通过这提供的思路,由于每个点处都需要90度的转弯,因此每个点处必然有一条横向以及一条纵向的路径穿过,单从某个x来看,由于上述限制,因此需要有偶数个点两两配对。然后通过搜索判断是否连通,最后再借助树状数组判断是否有自交的情况(”+”这种自交形状)出现。PS: 这里有个GDB的简单教程。#include #include #include using namespace std;const int MAXN = 10005;pair points[MAXN];vec 阅读全文
posted @ 2013-08-11 23:16 litstrong 阅读(261) 评论(0) 推荐(0) 编辑
摘要:再次回忆匈牙利算法和树状数组,除了算法的大概思路,其他已经不记得什么了。匈牙利算法:这个找二分图最大匹配的算法,就是不断的在当前匹配M上找这个匹配对应的一条增广路径P,根据M,P获得一个更大的匹配M',不断迭代直到找不到增广路径。树状数组:最简单的应用就是在log的时间级别更新、查询一个序列的区间和,通过维护数组数组可以在log时间内获得数组的前N项和,思路跟拆整数类似,一个整数可以拆成若干个二次幂的和,那么N项序列也可以拆成不超过logN个的2次幂个数的序列之和,C[i]用来记录A[i-2^r+1]...A[i]这些项,一共有2^r个项,r表示的是i写成二进制后末尾0的个数,有两个重 阅读全文
posted @ 2013-08-10 16:48 litstrong 阅读(278) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示