【Vijos1083】小白逛公园(线段树)
来源:互联网 发布:linux idea 安装jetty 编辑:程序博客网 时间:2024/04/28 05:52
题目:Vijos1083
分析:
一眼看上去就是线段树啊……
然而当我这种蒟蒻兴高采烈地把线段树模板敲了一半,却发现一个问题:
这子区间最大值的查询咋整啊……
于是经过仔cha细zhao思ti考jie,设计了这样一个线段树结点类型:
struct node{int val;int lm;int rm;int mm;}tree[2000010];val代表这个区间的总和,lm代表从左边往右搜的最大值,rm代表从右边往左搜的最大值,mm代表这个区间的子区间的最大值(就是要求的东西)
于是更新的时候
lm有两种情况:左子树的lm或者左子树全部加上右子树lm,rm同理
mm有两种情况:左子树/右子树mm的最大值或者左子树rm+右子树lm
inline void update(int r){tree[r].val=tree[r*2+1].val+tree[r*2+2].val;tree[r].lm=max(tree[r*2+1].lm,tree[r*2+1].val+tree[r*2+2].lm);tree[r].rm=max(tree[r*2+2].rm,tree[r*2+2].val+tree[r*2+1].rm);tree[r].mm=max(tree[r*2+1].rm+tree[r*2+2].lm,max(tree[r*2+1].mm,tree[r*2+2].mm));}
然后讨论本题最核心的部分:查询
查询区间只在mid的左边或右边都很“模板”,但是如果mid在查询区间中间就很坑,因为要保证区间是连续的
在这里,要查询左右两边,知道左右两边的val、lm、rm、mm,所以search函数要返回一个node结构
然后……就用跟上面的update类似的方法来处理出当前区间的val、lm、rm、mm(详见代码)
这样1...n区间返回的mm就是最终结果
代码:
#include<cstdio>#include<algorithm>using namespace std;struct node{int val;int lm;int rm;int mm;}tree[2000010];int n,m,in[500010];inline void update(int r){tree[r].val=tree[r*2+1].val+tree[r*2+2].val;tree[r].lm=max(tree[r*2+1].lm,tree[r*2+1].val+tree[r*2+2].lm);tree[r].rm=max(tree[r*2+2].rm,tree[r*2+2].val+tree[r*2+1].rm);tree[r].mm=max(tree[r*2+1].rm+tree[r*2+2].lm,max(tree[r*2+1].mm,tree[r*2+2].mm));}void build(int r,int lt,int rt){if(lt>rt)return;if(lt==rt){tree[r].val=tree[r].lm=tree[r].rm=tree[r].mm=in[lt];return;}int mid=(lt+rt)/2;build(r*2+1,lt,mid);build(r*2+2,mid+1,rt);update(r);}void change(int r,int lt,int rt,int p,int x){if(lt>rt||lt>p||rt<p)return;if(lt==rt){tree[r].val=tree[r].lm=tree[r].rm=tree[r].mm=x;return;}int mid=(lt+rt)/2;if(p<=mid)change(r*2+1,lt,mid,p,x);else change(r*2+2,mid+1,rt,p,x);update(r);}node search(int r,int lt,int rt,int ls,int rs){if(lt>rt||lt>rs||rt<ls)return (node){-0x3f3f3f3f,0,0};if(lt>=ls&&rt<=rs)return tree[r];int mid=(lt+rt)/2;if(rs<=mid)return search(r*2+1,lt,mid,ls,rs);else if(ls>mid)return search(r*2+2,mid+1,rt,ls,rs);else{node ln,rn,ans;ln=search(r*2+1,lt,mid,ls,rs);rn=search(r*2+2,mid+1,rt,ls,rs);ans.val=ln.val+rn.val;ans.lm=max(ln.lm,ln.val+rn.lm);ans.rm=max(rn.rm,rn.val+ln.rm);ans.mm=max(ln.rm+rn.lm,max(ln.mm,rn.mm));return ans;}}int main(void){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",in+i);build(0,1,n);while(m--){int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a==1){node ans=search(0,1,n,min(b,c),max(b,c));printf("%d\n",ans.mm);}elsechange(0,1,n,b,c);}return 0;}
阅读全文
0 0
- 【Vijos1083】小白逛公园(线段树)
- 【线段树】小白逛公园 Vijos1083
- bzoj 1756: Vijos1083 小白逛公园 (线段树)
- Vijos1083 小白逛公园(线段树+动态规划)
- 【BZOJ1756/Vijos1083】:小白逛公园 线段树
- 小白逛公园(vijos1083)
- 【BZOJ】【P1756】【Vijos1083 小白逛公园】【题解】【线段树】
- 1756: Vijos1083 小白逛公园
- bzoj1756 Vijos1083 小白逛公园
- 【vijos1083】小白逛公园
- bzoj1756: Vijos1083 小白逛公园
- 1756: Vijos1083 小白逛公园
- 小白逛公园 --线段树
- 小白逛公园(线段树)
- tyvj 1427 小白逛公园 (线段树)
- 线段树——vijos1083
- 线段树--小白逛公园nkoj1316
- vijos 小白逛公园(线段树单点更新)
- pair排序 线段覆盖 贪心
- MacOS 连接Cisco Console
- leanclude 数组查询问题
- C#中字符串的常用属性和方法
- Go语言并发编程总结
- 【Vijos1083】小白逛公园(线段树)
- 【学术篇】SDOI2010 古代猪文
- 深秋---JAVA 泛型
- 中国古代研究
- c语言指针相关概念
- ADB控制台过滤logcat信息
- web笔记三:Http协议中get和post请求
- 设计模式之单例模式
- nvm与nrm