博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P4513 小白逛公园 (线段树)
阅读量:5357 次
发布时间:2019-06-15

本文共 2340 字,大约阅读时间需要 7 分钟。

Solution

线段树是一门比较刁钻的手艺...

此题我们需要维护 \(4\) 个变量:

  1. \(amx\) 代表当前节点的最大值.
  2. \(lmx\) 代表当前节点以左端点为起点的区间最大值.
  3. \(rmx\) 代表当前节点以右端点为结尾的区间最大值.
  4. \(sum\) 代表整段的和.

然后我们在 \(push\)_\(up\) 的时候,也是要做蛮多工作.

\(lc\) 为左端点,\(rc\) 为右端点.

  1. \(lmx=max(lmx_{lc},sum_{lc}+lmx_{rc})\)

    也就是说可以单独取左儿子里的最大值,也可以一直取到右儿子的 \(lmx\) 为止.

  2. \(rmx=max(rmx_{rc},sum_{rc}+rmx_{lc})\)
    和上文同理.
  3. \(sum=sum_{lc}+sum_{rc}\)
  4. \(amx=max(amx_{lc},amx_{rc},rmx_{lc}+lmx_{rc})\)

    最关键的一步,更新每一个节点的答案. 可以在图上自己理解,此处不赘述.

特别注意,查询的时候也要把所有查出来的区间进行类似的操作...

Code

#include
using namespace std;const int maxn=1000008;struct node{ int l,r,lc,rc; int lmx,rmx,amx,sum;}sgm[maxn*4];int n,m,k,x,y;int cnt,a[maxn];void push_up(int x){ int ll=sgm[x].lc,rr=sgm[x].rc; sgm[x].sum=sgm[ll].sum+sgm[rr].sum; sgm[x].lmx=max(sgm[ll].lmx,sgm[ll].sum+sgm[rr].lmx); sgm[x].rmx=max(sgm[rr].rmx,sgm[rr].sum+sgm[ll].rmx); sgm[x].amx=max(max(sgm[ll].amx,sgm[rr].amx),sgm[ll].rmx+sgm[rr].lmx);}void build(int l,int r,int now){ sgm[now].l=l; sgm[now].r=r; if(l==r) { sgm[now].lmx=sgm[now].rmx=sgm[now].sum=sgm[now].amx=a[l]; return; } int mid=(l+r)>>1; sgm[now].lc=2*now; build(l,mid,sgm[now].lc); sgm[now].rc=2*now+1; build(mid+1,r,sgm[now].rc); push_up(now);}void change(int now,int to,int num){ int x=sgm[now].l,y=sgm[now].r; if(x==y) { sgm[now].lmx=sgm[now].rmx=sgm[now].sum=sgm[now].amx=num; return; } int mid=(x+y)>>1; if(to<=mid) change(sgm[now].lc,to,num); else change(sgm[now].rc,to,num); push_up(now);}node query(int now,int l,int r){ int x=sgm[now].l,y=sgm[now].r; if(l<=x&&r>=y) return sgm[now]; int mid=(x+y)>>1,ll=sgm[now].lc,rr=sgm[now].rc; if(r<=mid) return query(ll,l,r); else if(l>mid) return query(rr,l,r); else { node t,t1=query(ll,l,r),t2=query(rr,l,r); t.lmx=max(t1.lmx,t1.sum+t2.lmx); t.rmx=max(t2.rmx,t2.sum+t1.rmx); t.amx=max(max(t1.amx,t2.amx),t1.rmx+t2.lmx); return t; }}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); for(int i=1;i<=m;i++) { scanf("%d%d%d",&k,&x,&y); if(k==1) { if(x>y) swap(x,y); printf("%d\n",query(1,x,y).amx); } else change(1,x,y); } return 0;}

转载于:https://www.cnblogs.com/Kv-Stalin/p/9535100.html

你可能感兴趣的文章
iOS10 国行iPhone联网权限问题处理
查看>>
洛谷 P1991 无线通讯网
查看>>
Codeforces Round #178 (Div. 2) B. Shaass and Bookshelf 【动态规划】0-1背包
查看>>
SparkStreaming 源码分析
查看>>
【算法】—— 随机音乐的播放算法
查看>>
mysql asyn 示例
查看>>
数据库第1,2,3范式学习
查看>>
《Linux内核设计与实现》第四章学习笔记
查看>>
使用iperf测试网络性能
查看>>
图片的显示隐藏(两张图片,默认的时候显示第一张,点击的时候显示另一张)...
查看>>
Docker 安装MySQL5.7(三)
查看>>
python 模块 来了 (调包侠 修炼手册一)
查看>>
关于CSS的使用方式
查看>>
分析语句执行步骤并对排出耗时比较多的语句
查看>>
原生JS轮播-各种效果的极简实现
查看>>
计数器方法使用?
查看>>
带你全面了解高级 Java 面试中需要掌握的 JVM 知识点
查看>>
sonar结合jenkins
查看>>
解决VS+QT无法生成moc文件的问题
查看>>
AngularJs练习Demo14自定义服务
查看>>