摘要: http://acm.hdu.edu.cn/showproblem.php?pid=2795这题咋一看和线段树没啥关系似的。其实不然,非线段树不能解也!将黑板报上每一行看做一个节点线段,黑板的宽度为其容量,这样,H行黑板就对应了H个叶子节点。H的范围为10^9,看起来很大不是吗?我们再看通知的数目n,n的数目小于等于200000,也就是说,就算每一行都放一个通知,最多也只需要200000行,可见H<=10^9,这个纯属吓人的嘛为每个线段添加一个max_left域,表示该区间的最大剩余容量,采用先序遍历树的方式,在max_left>=(通知长度) 的情况下一直向下查找,知道找到根节点 阅读全文
posted @ 2011-11-10 19:57 Accept 阅读(213) 评论(0) 推荐(0) 编辑
摘要: http://poj.org/problem?id=2528又是一道区间染色问题,经典问题,自然有经典解法:为线段树添加一个cover域,当cover的值为-1的时候,则说明该区间是有多种颜色组成的。当cover为一个非-1的值时,说明该区间为cover一种颜色组成。更新的时候只需要将单色的区间信息向下传递即可这题唯一要做的,或许就是离散化吧。离散化就是利用数组的下标与其值一一对应的映射关系的一种hash。View Code 1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 usi 阅读全文
posted @ 2011-11-10 15:08 Accept 阅读(250) 评论(0) 推荐(0) 编辑
摘要: http://poj.org/problem?id=3468典型的一道基于lazy传递的线段树题目,这题和一般题目不同的地方在于,它的每次操作不是简单的覆盖线段,而是累加。记得第一次写的时候纠结了好久。好的,既然是累加,那么如何传递lazy呢?答案是传递累加值!为线段树加一个add域,表示该线段需要加几。如果某区间的add不为0,那么就将该区间的add传递给其子区间,并且跟新子区间的sum_val值。解这题最关键的就是要能够分清楚啥东西要传递,传递下去将有什么影响,其他的都好说!整体来说还是蛮轻松的View Code 1 #include<iostream> 2 #include& 阅读全文
posted @ 2011-11-09 21:28 Accept 阅读(233) 评论(0) 推荐(0) 编辑
摘要: http://poj.org/problem?id=2777又是一个区间染色问题,和一般的区间染色问题有点点不同,在于这题的线段范围比较大,如果采用cover域表示法的话会超时。所谓cover域表示法,即当cover值为-1时,表示该线段的颜色为混合色,要求的具体答案必须向下查找,直到找到cover不为-1的子区间。但是cover表示法也不错,因为我们有时候会别无选择。下面会为大家进行比较。先看这题的题解!这题虽然线段范围很大,但是我们注意到所用到的颜色最多只有30中,如果采用二进制压缩法的话,一个int 型数据即可以表示出所有的颜色(例如:1001表示了两种颜色,第一种和第四种) 。为线段树 阅读全文
posted @ 2011-11-09 21:08 Accept 阅读(310) 评论(0) 推荐(0) 编辑
摘要: http://acm.hdu.edu.cn/showproblem.php?pid=1394这道题属于利用线段树求解一个序列的逆序数的应用。由于题目要求有5000个数,普通方法求解逆序数必然导致超时( 时间为n*(n-1)/2 )。那么,利用线段树又如何求解呢?这里思维有些巧,假设有序列5 3 4 1 2。我们首先在线段[5,5]的位置上插入一个1,表示[5,5]这一线段有一个数,这个数就是5。接下来我们要插入3,在插入3之前,我们先查找一下[4,n]这一区间,看其中有多少个1,有多少个1,就表示4~n之内有多少个数在之前已经出现过了。这个值表示3的逆序数同理,一直插完最后一个数,我们便可以得 阅读全文
posted @ 2011-11-09 20:35 Accept 阅读(231) 评论(0) 推荐(0) 编辑
摘要: http://acm.hdu.edu.cn/showproblem.php?pid=1698这是一个区间染色的问题,对于区间染色问题,通常的方法是在线段树中定义一个cover域,当cover的值为-1的时候,则表示这个线段的覆盖不是有一个颜色染成的,其中包含了多种颜色,而当cover为一个非-1的值时,例如cover==1时表示该线段是有第一种颜色染成的。 对于这题,由于是成段成段的在跟新线段树,我们自然不能简单的递归到根节点再进行处理,这样毫无疑问是要超时的,所以我们只能成段的跟新。那么,如何做到成段的跟新呢?这里需要运用一种叫着lazy的思想,lazy顾名思义便是懒惰的意思。该思想大概的意 阅读全文
posted @ 2011-11-09 11:21 Accept 阅读(256) 评论(0) 推荐(0) 编辑
摘要: http://acm.hdu.edu.cn/showproblem.php?pid=1754这是一道运用线段树求解简单RMQ的题目,和敌兵布阵一样,这题的跟新操作也是对点进行的,即跟新时跟新到根节点即可,无需任何技巧。注意这题也是一点为基础单位(一个点代表一个学生),所以依然是建成点树。每次跟新后自下而上的进行最大值DP,为查询节约时间!View Code 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 struct node 6 { 7 int l; 8 int r; 9 int.. 阅读全文
posted @ 2011-11-09 10:54 Accept 阅读(190) 评论(0) 推荐(0) 编辑
摘要: http://acm.hdu.edu.cn/showproblem.php?pid=1166这是一道线段树的基础入门题,题目中的所有跟新操作都是对点进行的,也即无需任何lazy标记传递信息。由于是对点进行的操作,我们在建树的时候应该将数建成点树,即 build(2*i,l,mid); build(2*i+1,mid+1,r); 后面将会有需要段树的题目,待续。这题唯一的技巧应该就是查找了,我们在对某点进行跟新之后,可以采用之下而上的DP方式,跟新每一段中的人数信息,这样就可以为查找节约很多时间View Code 1 #include<iostream> 2 #include< 阅读全文
posted @ 2011-11-09 10:41 Accept 阅读(370) 评论(0) 推荐(0) 编辑
摘要: 首先、扩展欧几里得定理:对于两个不全为0的整数a、b,必存在一组解x,y,使得ax+by==gcd(a,b);实现如下:View Code int gcd(int a,int b){ int t,d; if(b==0) { x=1; y=0; //不明处1return a; } d=gcd(b,a%b); t=x; x=y; y=t-(a/b)*y; //不明处2return d;}上面的程序中,x和y我是用全局变量保存的我个人觉得第一次看到这个程序你会有以上两个不明白的地方(见注释),下面我分别解释不明处1:由... 阅读全文
posted @ 2011-09-02 22:29 Accept 阅读(17045) 评论(15) 推荐(11) 编辑
摘要: 1.题目大意: http://acm.hnu.cn/online/?action=problem&type=show&id=12022&courseid=186在布尔逻辑中,析取范式(DNF)是逻辑公式的标准化(或规范化),它是合取子句的析取。一个逻辑公式被认为是DNF的,当且仅当它是一个或多个文字的一个或多个合取的析取。同合取范式(CNF)一样,在DNF中的命题算子是与、或和非。非算子只能用做文字的一部分,这意味着它只能领先于命题变量。 简单来说,析取范式是一些字句的逻辑或,而它的字句是一个合取范式;合取范式是一些字句的逻辑或,而它的字句是一个析取范式。 本题中,逻辑 阅读全文
posted @ 2011-08-30 16:52 Accept 阅读(467) 评论(0) 推荐(0) 编辑