随笔分类 - 线段树&树状数组
摘要:问题:n个点,对于每个点i,都有一条连向i+1的有向边,另外有m条其他的有向边,有q个询问(u,v)求u到v的最短路将m条有向边和q个询问对所表示的点对一起排序,(u,v)u大的排前,u一样的v小的排前,u和v一样大的先处理插入的再处理询问的;边插入边询问;树状数组里存的是右端点在v之后的询问的结果的差值(1)对于(u,v)uv) 的那些还没插入,树状数组存mat[u1][v1]-(d[v1]-d[u1])的最小值,查询时在加上(d[v]-d[u])(2)对于(u,v)u>v的这种边,保证在查询到(u,v)之前,所有(u2,v2) v2#include #include #include
阅读全文
摘要:/*** 日期: 2013-9-12** 题目大意:有n个数,划分为多个部分,假设M份,每份不能多于L个。每个数有一个h[i],** 每份最右边的那个数要大于前一份最右边的那个数。设每份最右边的数为b[i],** 求最大的sum{b[i]² - b[i - 1]},1≤i≤M,其中b[0] = 0。** 思路:朴素DP为,dp[i]表示以i为结尾的最大划分。那么dp[i] = max{dp[j] - h[j] + h[i]²},** 1≤i-j≤L,h[j]<h[i]。这种会超时,采取线段树优化。因为有两个限制,考虑到若h[j]≥h[i],** 那么求i的时候一定不会用到j
阅读全文
摘要:树状数组是对一个数组改变某个元素和求和比较实用的数据结构。两中操作都是O(logn)。 在解题过程中,我们有时需要维护一个数组的前缀和S[i]=A[1]+A[2]+...+A[i]。 但是不难发现,如果我们修改了任意一个A[i],S[i]、S[i+1]...S[n]都会发生变化。 可以说,每次修改A[i]后,调整前缀和S[]在最坏情况下会需要O(n)的时间。 当n非常大时,程序会运行得非常缓慢。 因此,这里我们引入“树状数组”,它的修改与求和都是O(logn)的,效率非常高。【理论】 为了对树状数组有个形 象的认识,我们先看下面这张图。 如图所示,红色矩形表示的数组C[]就是树状数组。这里..
阅读全文
摘要:题目:http://acm.hdu.edu.cn/showproblem.php?pid=1166基维百科:http://zh.wikipedia.org/wiki/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84http://duanple.blog.163.com/blog/static/7097176720081131113145832/树状数组源码及部分注释:#include#include#define MAX 50010int N;int per[MAX],C[MAX];int lowbit(int n){//此函数实际就是将n的二进制表示形式留下最右边的1
阅读全文
摘要:好久没写过算法了,添一个吧,写一个线段树的入门知识,比较大众化。上次在湖大,其中的一道题数据很强,我试了好多种优化都TLE,相信只能用线段树才能过。回来之后暗暗又学了一次线段树,想想好像是第三次学了,像网络流一样每学一次都有新的体会。把问题简化一下:在自然数,且所有的数不大于30000的范围内讨论一个问题:现在已知n条线段,把端点依次输入告诉你,然后有m个询问,每个询问输入一个点,要求这个点在多少条线段上出现过;最基本的解法当然就是读一个点,就把所有线段比一下,看看在不在线段中;每次询问都要把n条线段查一次,那么m次询问,就要运算m*n次,复杂度就是O(m*n)这道题m和n都是30000,那么
阅读全文