1 条题解
-
0
线段树解区间求值最好了!
简介:
线段树是一种用于区间求值的数据结构,基于二叉树,下面我简单介绍一下在本题中用于求最值的线段树:
线段树主要是承担区间(单点)修改和区间(单点)查询。
线段树示意图:

操作:
更新操作,是建树()和修改((本题中用不到))后更新线段树数值的操作。
建树操作,具体见代码
询问操作,参考示意图。假如我们要求区间的最值,我们可以把区间拆成然后递归求。设要求的最值,那么只要是满足的节点,都可以纳入答案。我们不用递归到单点,如果有整段的,可以直接拿来用,这就是线段树的精髓罢。
代码:
#include<bits/stdc++.h> using namespace std; #define int long long const int MAXN=1000000007; int va[25005]; struct linetree { int l,r,sum;//结构体,本节点维护l——r的最值,sum为本节点的数值 } tree[125005]; void update(int now,int lson,int rson) {//与模板最不同的地方就是这里了 tree[now].sum=min(tree[lson].sum,tree[rson].sum);//当前节点是左右孩子的最小值 } void build(int now,int l,int r) {//建树,now为当前节点编号 tree[now].l=l; tree[now].r=r; if(l==r) { tree[now].sum=va[l]; return; } int mid=(l+r)>>1; int lson=now<<1;//将左孩子定到2*now位置 int rson=now<<1|1;//右孩子定到2*now+1位置 build(lson,l,mid);//继续向下建树 build(rson,mid+1,r);//同上 update(now,lson,rson);//递归回来更新当前节点 } int sum=MAXN; void ask(int now,int x,int y) {//区间求最值 if(x<=tree[now].l&&y>=tree[now].r) {//只要满足这个条件,就可以将它作为某段区间纳入答案 sum=min(sum,tree[now].sum); return; }//见注释的解释 int l=tree[now].l,r=tree[now].r; int mid=(l+r)>>1; int lson=now<<1; int rson=now<<1|1;//意义与建树是一样 if(x<=mid) ask(lson,x,y);//运用二分原理 if(y>mid) ask(rson,x,y); } signed main() { int n,m; cin>>n>>m; for(int i=1; i<=n; i++) cin>>va[i]; build(1,1,n);//可以参考示例图 for(int i=1; i<=m; i++) { int x,y; cin>>x>>y; sum=MAXN; ask(1,x,y); cout<<sum<<endl; } return 0; }
- 1
信息
- ID
- 2192
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者