题目链接:点击打开链接
代码1:
//线段树区间最值 #include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define maxn 200005 int num[maxn]; //纪录每个学生的成绩 struct segmentree { int l; //左端点 int r; //右端点 int maxc; //区间内最大分数 }; segmentree tree[4*maxn]; //总线段长度为N,开数组的话一般开到N的4倍 inline int Max(int a, int b) { return a > b ? a : b; } void build(int root,int l,int r) //root表示根节点,他的区间范围为[l,r] { tree[root].l=l; tree[root].r=r; if(tree[root].l==tree[root].r) //左右端点相等时就说叶子节点 { tree[root].maxc=num[l]; //赋初值 return ; } int mid=(l+r)/2; build(root<<1,l,mid); //建立左孩子节点 build(root<<1|1,mid+1,r); //root<<1|1相当于root*2+1;建立右孩子节点 tree[root].maxc=Max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值 } void update(int root,int pos,int v) //root是根节点,pos和v表示:更新pos处的值为v { if(tree[root].l==tree[root].r&&tree[root].l==pos) //叶子节点既是pos对应的位置 { tree[root].maxc=v; return ; } if(pos<=tree[root<<1].r) //如果pos点是在root对应的左孩子的话,就在左孩子中找 update(root<<1,pos,v); else update(root<<1|1,pos,v); tree[root].maxc=Max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值 } int query(int root,int l,int r) //询问[l,r]区间 { if(r<tree[root].l||l>tree[root].r) return 0; if(l<=tree[root].l&&r>=tree[root].r) //要查询的区间[l,r]包含root节点所表示的区间 return tree[root].maxc; int mid=(tree[root].l+tree[root].r)/2; int a=query(root<<1,l,r); int b=query(root<<1|1,l,r); return max(a,b); } int main() { int n,m,a,b; char str; while(scanf("%d%d",&n,&m)!=-1) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,1,n); //构造线段树根节点为1,表示区间范围[1,maxn] while(m--) { getchar(); scanf("%c%d%d",&str,&a,&b); if(str=='Q') { if(a>b) swap(a,b); printf("%d\n",query(1,a,b)); } else if(str=='U') { num[a]=b; update(1,a,num[a]); } } } return 0; }
代码2:
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define maxn 200005 int num[maxn]; //纪录每个学生的成绩 struct segmentree { int l; //左端点 int r; //右端点 int maxc; //区间内最大分数 }; segmentree tree[4*maxn]; //总线段长度为N,开数组的话一般开到N的4倍 void build(int root,int l,int r) //root表示根节点,他的区间范围为[l,r] { tree[root].l=l; tree[root].r=r; if(tree[root].l==tree[root].r) //左右端点相等时就说叶子节点 { tree[root].maxc=num[l]; //赋初值 return ; } int mid=(l+r)/2; build(root<<1,l,mid); //建立左孩子节点 build(root<<1|1,mid+1,r); //root<<1|1相当于root*2+1;建立右孩子节点 tree[root].maxc=max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值 } void update(int root,int pos,int v) //root是根节点,pos和v表示:更新pos处的值为v { if(tree[root].l==tree[root].r) //叶子节点既是pos对应的位置 { tree[root].maxc=v; return ; } int mid=(tree[root].l+tree[root].r)/2; if(pos<=mid) //如果pos点是在root对应的左孩子的话,就在左孩子中找 update(root<<1,pos,v); else update(root<<1|1,pos,v); tree[root].maxc=max(tree[root<<1].maxc,tree[root<<1|1].maxc); //更新父节点的maxc值 } int query(int root,int l,int r) //询问[l,r]区间 { if(l<=tree[root].l&&r>=tree[root].r) //要查询的区间[l,r]包含root节点所表示的区间 return tree[root].maxc; int mid=(tree[root].l+tree[root].r)/2; int cnt; if(r<=mid) cnt=query(root<<1,l,r); else if(l>mid) cnt=query(root<<1|1,l,r); else cnt=max(query(root<<1,l,tree[root<<1].r),query(root<<1|1,tree[root<<1|1].l,r)); return cnt; } int main() { int n,m,a,b; char str; while(scanf("%d%d",&n,&m)!=-1) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); build(1,1,maxn); //构造线段树根节点为1,表示区间范围[1,maxn] while(m--) { getchar(); scanf("%c%d%d",&str,&a,&b); if(str=='Q') { if(a>b) swap(a,b); printf("%d\n",query(1,a,b)); } else if(str=='U') { num[a]=b; update(1,a,num[a]); } } } return 0; }