纪中训练 day13 线段树
2018-02-06 16:33
134 查看
目录
例题
☞jzoj1959 最大值☜
大意
数据范围
思路
代码
☞jzoj1960最大值2☜
大意
数据范围
思路
代码
1 x y:表示修改A[x]为y
2 x y:询问x到y之间的最大值
输出每次询问的答案
例题
☞jzoj1959 最大值☜
大意
数据范围
思路
代码
☞jzoj1960最大值2☜
大意
数据范围
思路
代码
例题
☞jzoj1959 最大值☜
大意
一个长度为n的序列,m次操作,两种情况分别为1 x y:表示修改A[x]为y
2 x y:询问x到y之间的最大值
输出每次询问的答案
数据范围
1<=N<=M<=100000思路
一个很经典的线段树练习题,直接套模板代码
#include<bits/stdc++.h> #define N 1000007 using namespace std;int n,m; int a ; int x,y,tot; struct root{ int wz[N<<1]={0};//定义 void build(int k,int l,int r)//建造 { if(l==r) {wz[k]=a[l];return;} build(k<<1,l,(l+r)>>1); build((k<<1)+1,((l+r)>>1)+1,r); wz[k]=max(wz[k<<1],wz[k<<1|1]);//它的最大值等于它两个儿子的最大值 } void data(int k,int l,int r,int po,int val)//修改 { if(l==r) {wz[k]=val;return;}//只有一个了,那么直接修改 int mid=(l+r)>>1; if(po<=mid) data(k<<1,l,mid,po,val);//左区间 else data(k<<1|1,mid+1,r,po,val);//右区间 wz[k]=max(wz[k<<1],wz[k<<1|1]);//求最大值 } int qmax(int k,int l,int r,int ql,int qr)//在l到r之间找ql-qr的元素,k表示当前是第几个 { if(ql<=l&&r<=qr) return wz[k];//完全包含直接返回 int mid=(l+r)>>1,ret=0; if(ql<=mid) ret=max(ret,qmax(k<<1,l,mid,ql,qr));//访问左区间 if(mid+1<=qr) ret=max(ret,qmax(k<<1|1,mid+1,r,ql,qr));//访问右区间 return ret;//返回 } }tree; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]);//输入 tree.build(1,1,n);//建造 scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&tot,&x,&y); if(tot==1) tree.data(1,1,n,x,y);//修改 else printf("%d\n",tree.qmax(1,1,n,x,y));//输出 } }
☞jzoj1960最大值2☜
大意
和上题基本一致,不过这次是区间修改数据范围
1<=N<=M<=100000思路
利用懒惰标记,在每次查找的时候顺便下达命令。代码
#include<bits/stdc++.h> #define N 1000007 #define lson k<<1 #define rson k<<1|1 using namespace std;int n,m; long long a ; int x,y,tot;long long z; long long max(long long x,long long y){return x>y?x:y;} struct ST{ long long wz[N<<2]={0},add[N<<2]={0}; void down(int k,int l,int r)//下达命令 { if(!add[k]) return; if(l!=r) {add[lson]+=add[k];add[rson]+=add[k];} wz[k]+=add[k];add[k]=0;return ; } void build(int k,int l,int r)//建造 { if(l==r) {wz[k]=a[l];return;} build(lson,l,(l+r)>>1); build((lson)+1,((l+r)>>1)+1,r); wz[k]=max(wz[lson],wz[rson]); } void change(int k,int l,int r,int ql,int qr,long long c)//改变一个区间的值 { down(k,l,r); if(ql<=l&&r<=qr) {add[k]+=c;return;} int mid=(l+r)>>1; if(ql<=mid) change(lson,l,mid,ql,qr,c); if(qr>=mid+1) change(rson,mid+1,r,ql,qr,c); down(lson,l,mid);down(rson,mid+1,r); wz[k]=max(wz[lson],wz[rson]); } long long qmax(int k,int l,int r,int ql,int qr)//查找一个区间的最大值 { down(k,l,r); if(ql<=l&&r<=qr) return wz[k]; int mid=(l+r)>>1;long long ret=-214748364; if(ql<=mid) ret=max(ret,qmax(lson,l,mid,ql,qr)); if(mid+1<=qr) ret=max(ret,qmax(rson,mid+1,r,ql,qr)); return ret; } }tree; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); tree.build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&tot,&x,&y);//输入 if(tot==1) {scanf("%lld",&z);tree.change(1,1,n,x,y,z);}//修改 else printf("%lld\n",tree.qmax(1,1,n,x,y));//输出 } }
相关文章推荐
- CUGB专题训练之数据结构:A - Balanced Lineup(线段树单点或RMQ)
- POJ训练计划2777_Count Color(线段树/成段更新/区间染色)
- 算法训练 操作格子 线段树板子题
- 【学姐的胡策】训练8.17(Lucas+线段树并查集)
- 纪中训练 day1 【NOIP普及组】模拟赛D组 解题报告
- POJ训练计划2828_Buy Tickets(线段树/单点更新)
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 训练之线段树I Hate It
- 【hdu 2795】Billboard 【线段树训练 3】
- 线段树专题#4_蒟蒻训练历程记录_HDU1698_ 延迟标记、区间更新
- POJ训练计划2299_Ultra-QuickSort(线段树/单点更新)
- 2016寒假训练——线段树
- 暑期训练狂刷系列——Hdu 1698 Just a Hook (线段树区间更新)
- 多校训练hdu --Nice boat(线段树,都是泪)
- 2017/8/17训练日记 (线段树详解)
- 蓝桥杯 算法训练 操作格子 (线段树)
- 蓝桥杯_法训练—操作格子(线段树点更新与区间查询)
- 线段树专题训练
- 蓝桥杯 算法训练 校门外的树(线段树+懒惰标记)
- hdu线段树专题训练