随笔分类 -  ACM_数据结构

摘要:题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 题意:给定一颗有根树,每个节点有0和1两种值。有两种操作:o a操作,把以a为根节点的子树的权值全部取反;q a操作,求以a为根节点的子树权值为1的节点个数。 先求出树的先序遍历结果,并且记录每颗子树的节点个数,然后就可以用线段树维护了。。 1 //STATUS:C++_AC_240MS_6524KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7 #i... 阅读全文
posted @ 2014-03-03 17:38 zhsl 阅读(310) 评论(0) 推荐(0)
摘要:题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3349 题意:给定一个数列,序列A是一个满足|Ai-Ai-1| 3 #include 4 #include 5 //#include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include ... 阅读全文
posted @ 2014-03-03 17:29 zhsl 阅读(340) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3874 比较简单的题,题意也好懂。 先O(n)求每个数左边第一次出现的与他相同的数的位置l[i]。对询问按照y从小大排序,然后按照从左到右的顺序来跟新点,当前点为i,那么删掉l[i],加入点i,然后遇到询问求和。 1 //STATUS:C++_AC_2593MS_10024KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7 #include 8 #include 9 #include 1... 阅读全文
posted @ 2013-10-31 00:43 zhsl 阅读(282) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3872 题意:有n个龙珠按顺序放在一列,每个龙珠有一个type和一个权值,要求你把这n个龙珠分成k个段,每段的权值是这段中的最大的权值,使得最后的权值之和最小。但是现在有个要求,分的段中,龙珠的type不能和最右边的相等。 容易想到是一个DP:f[i]=Min{f[j]+Min(j,i) | j是满足要求的点}。直接搞的话O(n^2),显然超时了。但是可以发现,这个Min(j,i)是有分段性的,因此我们可以维护一个单调递减的栈,那么只要求栈中的元素就可以了,因为只有这些元素有效。这里还要求最... 阅读全文
posted @ 2013-10-31 00:39 zhsl 阅读(397) 评论(0) 推荐(0)
摘要:题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1998 题意:有n个石头,每个石头有个重量,每个时间点你能让一个石头飞起来,但有m个时间点,你会分心,使得已经飞起来的石头会有重量之和大于k的石头掉下来,问你最终使的所有石头飞起来的时间。 维护一个前缀和,然后二分就可以了。 1 //STATUS:C++_AC_93MS_1113KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7 #include 8 #include 9 #incl... 阅读全文
posted @ 2013-10-31 00:22 zhsl 阅读(347) 评论(0) 推荐(0)
摘要:题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1989 题意:给出一个字符串,m个操作:1,修改其中一个字符串,2,询问 [a, b] 是不是回文串。数据范围10^5。 如何快速判断字符串是不是回文串,可以用到多项式Hash。假设一个串s,那么字串s[i, j]的Hash值就是H[i, j]=s[i]+s[i+1]*x+s[i+2]*(x^2)+...+s[j]*(x^(i-j))。由于只有小写字母,因此x取27。但是H[i, j]这会很大,我们取模就可了,可以把变量类型设为unsigned long long, 那么自动溢出就相当 阅读全文
posted @ 2013-10-30 00:34 zhsl 阅读(963) 评论(0) 推荐(0)
摘要:题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1987 题意:给定n条线段,每两条线段要么满足没有公共部分,要么包含。给出m个询问,求当前点被覆盖的最小长度的线段编号。 由于线段不存在部分相交的情况,因此,直接按照输入顺序覆盖区间就可以了,因为后覆盖的线段更短。 1 //STATUS:C++_AC_187MS_6805KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7 #include 8 #include 9 #include ... 阅读全文
posted @ 2013-10-30 00:23 zhsl 阅读(847) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:求一个数列中,所有mex(L,R)的和。 注意到mex是单调不降的,那么首先预处理出mex(1,j)的值,复杂度O(n),因为mex最大为n。同时预处理出每个数a[i]的右边第一次出现a[i]的位置,用next[i]表示。然后依次从1开始枚举起点 i,则就是求 i 到n的所有mex的和了。i从i+1变化,j>next[i]的mex值都不会变化,因为还是存在a[i]。那么只要考虑i+1到next[i]-1这个区间了,这个区间中,mex第一次大于a[i]的位置k,[k,next[i. 阅读全文
posted @ 2013-09-28 01:06 zhsl 阅读(453) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4742 题意:求3维的LIS。。 用分治算法搞得,参考了cxlove的题解。。 首先按照x排序,然后每个三元组一个编号1-n。接下来只要考虑y和z的值,假设[l,mid]区间已经求好,那么我们对[l,r]区间按照y排序,更新[mid+1,r]区间的最优值时,只要考虑z值了,用树状数组维护z的最长LIS,遇到[mid+1,r]区间的就更新。 1 //STATUS:C++_AC_1750MS_5348KB 2 #include 3 #include 4 #include 5 /... 阅读全文
posted @ 2013-09-28 00:39 zhsl 阅读(626) 评论(1) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4737 题意:给一个数列a0, a1... , an-1,令f(i, j) = ai|ai+1|ai+2| ... | aj,求数列中有多少对f(i,j)满足f(i,j) 3 #include 4 #include 5 //#include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #i... 阅读全文
posted @ 2013-09-28 00:12 zhsl 阅读(311) 评论(0) 推荐(0)
摘要:摘自:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html“在一棵树上进行路径的修改、求极值、求和”乍一看只要线段树就能轻松解决,实际上,仅凭线段树是不能搞定它的。我们需要用到一种貌似高级的复杂算法——树链剖分。树链,就是树上的路径。剖分,就是把路径分类为重链和轻链。记siz[v]表示以v为根的子树的节点数,dep[v]表示v的深度(根深度为1),top[v]表示v所在的链的顶端节点,fa[v]表示v的父亲,son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子),w[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位.. 阅读全文
posted @ 2013-09-09 23:21 zhsl 阅读(244) 评论(0) 推荐(0)
摘要:题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=29359 题意:一个数列,有三种操作: 1.区间[a,b]之间大于零的数整出c。 2.区间[a,b]之间所有的数减去c。 3.求区间[a,b]的和。 只要注意到每个数最多除lgn次,总共除n*lgn次,那么直接对除法进行单点更新就可了,关键要分析好复杂度。。 1 //STATUS:C++_AC_3020MS_33996KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7... 阅读全文
posted @ 2013-09-06 00:13 zhsl 阅读(308) 评论(0) 推荐(0)
摘要:题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=26475 题意:每次输入一个操作,如果是数字,那么放入一个容器中,如果是#号,取出当前容器中的中间值。。 数据结构基础题,显然维护两个堆就可以了,两个堆的size大小不超过1... 其实各种数据结构都可以搞,比如线段树,先离线然后离散,然后线段树记录size,二分查找。。 1 //STATUS:C++_AC_856MS_3192KB 2 #include 3 #include 4 #include 5 //#include 6 #include 7 #include ... 阅读全文
posted @ 2013-08-26 10:14 zhsl 阅读(232) 评论(0) 推荐(0)
摘要:题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=26474 题意:给一个数列,可以对三个数操作:把最后一个数放到第一个,前两个数后移一位。问最后能否到达相应的目标序列。。 先考虑三个数A B C,变换后两种情况B C A和C A B,可以证得(列举3个数的大小情况,枚举证),这三个序列变换后的逆序对个数的奇偶性是相同的,而且只有这3个序列相同,所以A B C只能到达与之奇偶相同的序列,而且是全部能到达。那么多个数的情况也是一样的,就是多个3元组的扩展。因此如果变换后的逆序奇偶性相同,那么有解,否则无解。。 1 //STATUS... 阅读全文
posted @ 2013-08-26 10:09 zhsl 阅读(312) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4699 题意:开始有一个光标,每次有5中操作:1,光标当前位置插入一个数,2,光标当前位置删除一个,3,光标向左移一位,4,光标向右移动一位,5,询问前面的数列的最大前缀和。 由于每次删除的数都是在当前的光标位置,而且询问的前缀和都是在光标前面的位置,因此问题简化了很多,否则要用Splay tree搞了。我们可以直接用一个链表或者两个栈来维护光标以前的最大前缀和,然后直接模拟操作就可以了。。。 1 //STATUS:C++_AC_671MS_10824KB 2 #include 3 #in... 阅读全文
posted @ 2013-08-22 19:42 zhsl 阅读(427) 评论(0) 推荐(0)
摘要:转自:http://blog.sina.com.cn/s/blog_7812e98601012cim.html函数式(现在又称主席式。。。)数据结构从来都没写过,感觉这个东西可以挖掘出不少东西出来,于是开一组专题。先根据Seter 留下的文本做一些记录。。主席树大概是一种离线结构,我以前反正没看到过这东西,所以就自己给他起名字了!如果谁知道这东西的真名,请告诉我!现在我们知道,主席树的全名应该是 函数式版本的线段树。加上附带的一堆 technology。。。。总之由于原名字太长了,而且 “主席” 两个字念起来冷艳高贵,以后全部称之为主席树好了。。。主席树的主体是线段树,准确的说,是很多棵线.. 阅读全文
posted @ 2013-08-19 02:13 zhsl 阅读(371) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4666 题意:动态的增加或者删掉k维空间的点,求每次操作后剩下的点集中的最大的麦哈顿距离。 如果是一维情况很好做,直接用个数据结构来维护就行了,那么多维情况怎么办?其实多维情况是可以降到一维情况的。考虑二维的情况:|xi-xj|+|yi-yj|,我们展开绝对值之后,就可以得到四个式子:(xi+yi)-(xj+yj), (-xi+yi)-(-xj+yj), (xi-yi)-(xj-yj), (-xi-yi)-(-xj-yj),根据不等式 |x|+|y|>=x+y,那么我们对所有的点求出(xi+. 阅读全文
posted @ 2013-08-13 21:48 zhsl 阅读(407) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4630 题意:给一个数列,询问区间[l,r]里两个数最大gcd。 求区间的最大gcd(a,b),就是找一个数是在这个区间所有数的约数中,至少出现两次,而且最大的那个数。那么接下来就比较容易了,从右到左扫描数列,用pre[i]表示约数 i 在当前这个位置往右第一次出现的位置,那么每到一个位置枚举num[i]的所有约数,然后用树状数组维护一个区间最大值就行了,用树状数组维护区间最大值有点麻烦,但这里是从右往左扫描的,因此可以求0-i点的最大值,就很简单了。。。 1 //STATUS:C++_A... 阅读全文
posted @ 2013-08-03 00:51 zhsl 阅读(516) 评论(0) 推荐(0)
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4638 个人认为比较不错的题目。 题意:给一个1-n的排列,询问区间[l,r]的数排序后连续区间的个数。 对于这种题目容易想到对询问离线处理,难点是怎样在logn的时间内求出连续区间的个数。先对询问按右端点y从左到右排序,然后从左到右扫描整个数列,现在考虑加一个数num进去,如果我们前面存在num-1或者num+1,那么数列连续区间的个数是没有增加的,可能还会减少。因此我们可以维护一个数组数组或者线段树,对于每加进去的一个数num[i],对 i 点加1,如果 i 点前存在num[i]-1和... 阅读全文
posted @ 2013-08-02 21:04 zhsl 阅读(254) 评论(0) 推荐(0)
摘要:题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1500DescriptionInput输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。 第2行包含N个数字,描述初始时的数列。 以下M行,每行一条命令,格式参见问题描述中的表格。Output对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。Sample Input9 82 -6 3 5 1 -5 -3 6 3GET-SUM 5 4MAX-SUMINSERT 8 3 -5 7 2DELETE 12 .. 阅读全文
posted @ 2013-07-31 12:55 zhsl 阅读(701) 评论(0) 推荐(0)