原题地址:点击打开链接

这题花了整整一天来做,错误基本都是TLE,但是做完非常哈皮,因为感觉比较好地运用了线段树这个数据结构。话说这几天广东不是一般热,中午根本睡不着,满身黏糊糊,课室和图书馆倒成了平时宅男的去处,不过这仅仅限于他们宿舍没有开空调的情况下·····然后昨天的过劳导致了今天的脖子和肩膀连成一片的疼,而且我能明显感觉到头脑恍惚。

呃,这题我感觉是可以好好写,但是感觉现在写解题报告好像变懒了,懒不得懒不得,等会儿妹子下课了去吃个雪糕,夏日已来么?

————————正文————————

我看了一下网上各位大牛的代码,可以说我的代码还是比较短的,当然也达到了120行的水平,哎可能是“自家孩子最漂亮”的缘故,哈哈,若有冒犯多多包涵。

这题的数据设计得非常恰到好处,就掐着你O(n^2)的算法肯定是过不了的,数据一点都不水。下面说下这题的思路。

线段树其实是个比较容易弄懂的东西,在这题上面,唯一的难点就是如果查询的范围刚好跨了两棵子树怎么办?下面以有5个数字的序列举例,其线段树如下:

上面每个节点都保存了这一段的最大连续和(smax),获得最大连续和时的左下标和右下标(sl和sr)。

最大连续和smax怎么来?

1. 可能是从左子树来

2. 可能是从右子树来

3. 可能是:左子树中包含最右序号的最大连续和+右子树中包含最左序号的最大连续和

对于节点(1,5),如果碰到情况3,那么就要知道:a. 当前节点的左儿子在包含最右序号(即3)时的最大连续值; b. 以及右儿子在包含最左序号(即4)时的最大连续值,然后相加即可。

将a中的值保存在节点的rmax中,而达到rmax时的左序号保存在rmn中;同理将b中的值保存在节点的lmax中,达到lmax时的右序号保存在lmn中。

(说了这么多,是不是觉得很乱,其实不用太过咬文嚼字,先有个大概想下你觉得应该是怎么计算的,然后再来套上面这些文字。)

现在另外一个问题来了,怎么计算rmax和lmax?如果每次都额外再用O(N)的算法来计算当前节点的lmax和rmax,那么会超时,为什么呢,粗略可以估计一下线段树的节点数是2N,如果对每个节点都使用O(N)的算法来计算那么将会达到O(N^2)复杂度,会直接卡死。所以要找O(1)的方法。

其实稍微思考下,当前节点的lmax,rmax可以由两个子节点得到,lmax不外乎以下2种情况:

1. 左儿子的所有元素和+右儿子的lmax

2. 左儿子的lmax

rmax同理,所以这个问题也解决了。

如果我查(2, 5)的最大连续和那怎么办?很明显这个查询在去到(1,5)的时候就会卡住,我们知道,其实(1,5)的最大值可能是以下三种情况之一:

1. 可能是(2,3)的最大值

2. 可能是(4,5)的最大值

3. 可能是(2,5)中同时包含下标3和4的子集的最大值,如(2,4),(2,5),(3,4),(3,5)

我们使用的是递归查找,情况1和情况2都可以直接往下走,因为这两种情况下序列的范围是儿子节点的序列范围的子集

对于情况3,其实十分类似找lmax与rmax,但是要计算必须知道子节点的lmax与rmax,(2,5)的子节点是什么?问得好,其实我们对于每一个查询,重新建立一棵临时的树就好了,要注意的是这棵树可能不是平衡的,可能左树高点,可能右树高点,但是计算方法是一样的。对于(2,5),临时的线段树如下:

这棵树的建立方法基本相同,具体参见代码即可,看懂了上面代码也非常容易看明白了。多说一句,用cin和cout会超时

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#define RANGE 100005
#define INF 0x7fffffff
using namespace std;
struct node
{int l,r,sum;            //当前节点左边界、右边界、元素总和int lmn,rmn,lmax,rmax;  //从左边界开始连续到第lmn位置元素和,有最大值lmax//从右边界开始连续到第rmn位置元素和,有最大值rmaxint lson,rson;           //节点左儿子和右儿子的编号int sl,sr,smax;         //当前序列从sl到sr能取得最大连续值smax
}nn[RANGE*6];               //输入的线段树需要的空间为2*N(开3*N的数组),计算时建立新树,故翻倍
int n,m,a[RANGE*2];
int nnum;                   //每次解决查询时,建立新的线段树节点的开始下标void computeMax(int index, int ls, int rs)//计算index节点的sum,sl,sr,smax,lmn,lmax,rmn,rmax
{int tmp;nn[index].sum=nn[ls].sum+nn[rs].sum;nn[index].smax=nn[ls].smax;nn[index].sl=nn[ls].sl;nn[index].sr=nn[ls].sr;tmp=nn[ls].rmax+nn[rs].lmax;if(tmp>nn[index].smax || (tmp==nn[index].smax && nn[ls].rmn<nn[index].sl)){nn[index].smax=nn[ls].rmax+nn[rs].lmax;nn[index].sl=nn[ls].rmn;nn[index].sr=nn[rs].lmn;}if(nn[rs].smax>nn[index].smax){nn[index].smax=nn[rs].smax;nn[index].sl=nn[rs].sl;nn[index].sr=nn[rs].sr;}//计算当前节点的lmax与rmaxtmp=nn[ls].sum+nn[rs].lmax;if(tmp>nn[ls].lmax){nn[index].lmax=tmp;nn[index].lmn=nn[rs].lmn;}else{nn[index].lmax=nn[ls].lmax;nn[index].lmn=nn[ls].lmn;}tmp=nn[rs].sum+nn[ls].rmax;if(tmp>=nn[rs].rmax)//注意等于号{nn[index].rmax=tmp;nn[index].rmn=nn[ls].rmn;}else{nn[index].rmax=nn[rs].rmax;nn[index].rmn=nn[rs].rmn;}
}
int compute(int l, int r, int index)
{if(l==nn[index].l && r==nn[index].r)return index;int ls=index*2;      //左二子标号int rs=index*2+1;   //右儿子标号if(r<=nn[ls].r)return compute(l,r,ls);else if(l>=nn[rs].l)return compute(l,r,rs);else{int nindex=nnum++;nn[nindex].l=l; nn[nindex].r=r;nn[nindex].lson=compute(l,nn[ls].r,ls);nn[nindex].rson=compute(nn[ls].r+1,r,rs);computeMax(nindex, nn[nindex].lson, nn[nindex].rson);return nindex;}
}
void buildTree(int l, int r, int index)
{nn[index].l = l;nn[index].r = r;if(l==r){nn[index].sum=nn[index].smax=nn[index].lmax=nn[index].rmax=a[l];nn[index].lmn=nn[index].rmn=nn[index].sl=nn[index].sr=l;return;}int mid=(l+r)/2;int ls,rs;   //左右儿子编号ls=index*2; rs=index*2+1;buildTree(l,mid,ls);buildTree(mid+1,r,rs);computeMax(index, ls, rs);
}
int main()
{//freopen("in","r",stdin);//freopen("out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",&a[i]);buildTree(1,n,1);for(int i=1;i<=m;++i){int tmpa,tmpb;scanf("%d%d",&tmpa,&tmpb);nnum=3*n+1;int nindex = compute(tmpa,tmpb,1);printf("%d %d %d\n", nn[nindex].sl, nn[nindex].sr, nn[nindex].smax);}
}                                 

******<转载说明>******
转载注明:诚实的偷包贼
原文地址:http://blog.csdn.net/fanfank/article/details/8930394
******<转载说明/>******

Sicily 1136 山海经 (SOJ 1136) 【Segment Tree 线段树】相关推荐

  1. C++SEG TREE线段树的实现算法(附完整源码)

    C++SEG TREE线段树的实现算法( C++SEG TREE线段树的实现算法(完整源码(定义,实现,main函数测试) C++SEG TREE线段树的实现算法(完整源码(定义,实现,main函数测 ...

  2. HDU - 3333 Turing Tree 线段树区间不同值和+详解+思想

    传送门 首先第一次做这种求不同元素和的线段树题,猜想是个裸题.但是题目中有一句话显然给题目降低了很大的难度,就是 想想其实它就是在暗示你这道题你要结合多次询问来处理,也就是所谓的离线,而不是一次一次的 ...

  3. CodeForces - 620E New Year Tree(线段树+dfs序+状态压缩)

    题目链接:点击查看 题目大意:给出一棵无向树,每个节点都有一种颜色,接下来时m次操作: 1 x y:将x及其子树染成y的颜色 2 x:查询x及其子树上共有多少种不同的颜色 题目分析:看完这个题的第一反 ...

  4. HDU - 3333 Turing Tree(线段树+离线处理)

    题目链接:点击查看 题目大意:给定一个长度为n的数列,依次求m个区间中不相同数字之和 题目分析:n给的是3e4,看到区间问题先要想到线段树或差分区间或动态规划,暴力是肯定不行滴,那么这个题已经知道是需 ...

  5. 【BZOJ 3165】 [Heoi2013]Segment 李超线段树

    所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #in ...

  6. hdu 6962 I love tree 线段树维护二次函数

    传送门 文章目录 题意: 思路: 题意: 给你nnn个点的一颗树,有mmm次询问,每次询问有两个操作: (1)(1)(1)将[a,b][a,b][a,b]路径上的点依次加上12,22,32,...,l ...

  7. P4097 [HEOI2013]Segment 李超线段树

    传送门 文章目录 题意: 思路: 题意: 实现以下两个操作: (1)(1)(1)在平面上加入一条线段.记第iii条被插入的线段的标号为iii (2)(2)(2)给定一个数kkk,询问与直线x=kx=k ...

  8. P4097 [HEOI2013]Segment 李超线段树

    $ \color{#0066ff}{ 题目描述 }$ 要求在平面直角坐标系下维护两个操作: 在平面上加入一条线段.记第 i 条被插入的线段的标号为 i 给定一个数 k,询问与直线 x = k 相交的线 ...

  9. CF 242E XOR on Segment 【线段树】

    两种操作: 1.求区间和 2.对区间上的每一个数进行异或(xor)运算 直接维护区间和的话区间更新无法进行,所以,要维护的信息是区间内按位和(即每个二进制位出现的次数),那么进行xor运算的时候,只需 ...

最新文章

  1. 八种基本类型的包装类你真的懂了?
  2. Element 2.6.0 发布,基于 Vue 2.0 的桌面端组件库
  3. python学习笔记(四)-数据类型
  4. Android Service使用方法--简单音乐播放实例
  5. 解决LiteIDE 中的error process failed to start.
  6. FreeMarker生成word的代码
  7. 窗口分析函数_9_计算组内总和的占比
  8. 水阀门开关方向图解_低压阀门开闭器
  9. 第一次摸服务器遇到的问题总结
  10. Eclipse使用时的一些小积累
  11. CaffeMFC:caffe.pb.h(2525): error C2059: syntax error : 'constant'
  12. 物业公司工作流应用方案
  13. 支持向量所在超平面方程_深入浅出机器学习算法:支持向量机
  14. ivx中字体显示_Windows 7 中的 SimSun-ExtB 是什么字体,为何与中易宋体 SimSun 显示出来不一样?...
  15. 你只管打开这个网站,剩下的交给「卧槽」!
  16. 项目管理系统设计方案
  17. 计算机一级excel试题百度云,excel计算机一级试题
  18. 短信验证码接收app必须注意的那些事
  19. 4.10招商银行笔试编程题
  20. 如何安装torch、Pytorch、torchversion

热门文章

  1. 自定义Win7虚拟机的睡眠时间
  2. 5.4 微程序控制器
  3. plotly绘制简单图形4--饼形图
  4. 互联网创业公司融资、产品、运营快速迭代和人才模式总结
  5. Qt opengl fps相机
  6. 1227: 苹果和虫子
  7. 计算机显示在屏幕上怎么取消,电脑显示屏显示的九宫格怎样取消掉
  8. 关于星巴克推广活动的实验测试
  9. 剪辑过的视频md5会改变
  10. 懒人库ButterKnife的应用