线段树学习
来源:互联网 发布:米兔机器人如何编程 编辑:程序博客网 时间:2024/05/16 05:33
原文地址:http://blog.csdn.net/zxy_snow/article/details/6636162
&& http://blog.csdn.net/zxy_snow/article/details/6676302
一、建图
我感觉,线段树的建图有两种。
1、最后一层建成线段,就是所有区间都是开区间,最后一层是[1,2] [2,3] [3,4]什么的。
2、最后一层建成点,类似[1,1] [2,2]..
今天建了下,个人比较喜欢第一种建法~感觉正好就是线段嘛。
建树我用的数组模拟邻接表,本来是想用指针的,不过感觉挺麻烦的,如果用指针的话就不能用位运算了哈。建树很简单,线段树是递归定义的,所以建树也是递归就好。
树的左右孩子直接由数组下标去寻找,左孩子是2*x,右孩子是2*x+1
#define L(x) x << 1#define R(x) x << 1 | 1
根据题目的不同,树的结点可以增加其他的值去标记一些东西。比如我今天过的两个题,是标记颜色值,或者是否覆盖的。
void Build(int t,int l,int r){node[t].cover = 0;node[t].l = l;node[t].r = r;if( l == r-1 )return ;int mid = (l+r)>>1;Build(L(t), l, mid);Build(R(t), mid, r);}二、更新(我更喜欢叫更新是Updata。。。虽然准确的说应该是Update。。。)
1、注意更新父节点对子节点的影响。
2、注意更新子节点对父节点的影响。
3、开始我一直拿初始的l 和 r去更新,根本没用用到mid。后来问兴海,他说有的时候会有用。想了下,如果跟覆盖的区间有关的话,应该还是得用到,不过这两题都没用到 = =。。
4、如果父节点已经被覆盖过的话,如果这个父节点的子节点需要覆盖其他的颜色的话,父节点的颜色需要往子节点传递,才能保证这个线段不被多个颜色覆盖。传递后,这个父节点颜色就没有了,标记成-1。
void Updata(int t,int l,int r,int col){if( r <= l ) return ;if( l <= node[t].l && node[t].r <= r ) {node[t].cover = col;return ;}int mid = (node[t].l + node[t].r) >> 1; if( node[t].cover > 0 ){node[R(t)].cover = node[t].cover;node[L(t)].cover = node[t].cover;node[t].cover = -1;}if( l >= mid )Updata( R(t), l, r, col);elseif( r <= mid )Updata( L(t), l, r, col);else{Updata( L(t), l, mid, col);Updata( R(t), mid, r, col);}}
大致分为这几类
操作:
1、区间覆盖,染色啊,异或啊,加上一个数,乘一个数,都变成某个数啊神马的。
2、涉及矩形的一些方法。
3、区间单值更新。
4、类似二分的查找位置。
5、类似约瑟夫环的一些东东。
6、。。。。
询问:
1、区间最值,第K值。
2、区间和,各种和。
3、区间连续区域的位置,连续区域最大长度。
4、和DP一起,区间最长XX子序列神马的。
5、。。。。
目前见过的就这几种吧,其实看起来蛮少的。恶心的是好几种操作,好几种询问混到一道题上,想shi。。
而且写线段树特别需要头脑清楚,因为设计好线段树的域很重要,而且需要想清楚各种更新,稍不留神就挂了。
能用函数写尽量用函数,要不写着写着会晕的。
LAZY标记是个很强大也很讨厌的东东 T T 。。。它省了好多时间,不过更新细节需要狠狠注意。
二维线段树我只会用树套树解决很水的问题,什么四分树不会,见的题不多。
合适的节点设计会省事很多,我越来越懒了 = =。。struct里加了好几个函数。
我的一维线段树的定义。不过就纠结的是,不能使用名字为len的变量了 = =。。
struct Tnode{ int l,r,val; long long sum; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;}};二维的,基本和一维函数都差不多。
struct T2node{ int l,r; Tnode son[MAXM<<2]; int len() { return r - l;} int mid() { return MID(l,r);} bool in(int ll,int rr) { return l >= ll && r <= rr; } void lr(int ll,int rr){ l = ll; r = rr;} };
- 学习线段树
- 线段树学习入门
- 留待学习线段树
- 线段树学习
- 线段树学习
- 线段树学习
- 线段树 学习资料
- 学习笔记 线段树
- 线段树学习小结
- 线段树学习
- 线段树学习
- 线段树学习记录
- 线段树学习
- 线段树学习
- 线段树学习
- 线段树学习笔记
- 线段树学习笔记
- 学习笔记 --- 线段树
- linux创建连接命令ln -s软链接
- 一种较方便在Android中添加开机自启动的守护进程的方法
- vector tip
- 多维数组与指针 精析
- 深入浅出FPGA-14-ChipScope软件使用
- 线段树学习
- Don't Track Me Google
- SQLite运行在WinRT, Metro以及Win 8移动版
- 子页面执行父页面Javascript方法
- 【项目总结】-Android Service用法总结
- Query插件有多少
- 那些让我心酸的:微小说
- 在eclipse下使用java调用weka
- 条形码 生成条形码