输入
第一行两个整数n,m,第二行n个整数表示初始时的数组A[ ];
接下来m行,每行3个整数a,b,c,如果a=1,那么输出A[b]~A[c]中最大的数
若a=2,那么将A[b]改为c
输出
每行输出一个整数,对应每一个操作a=1
超级简单的线段树模板题,一遍就过了,子程序太多,变量更多,容易搞混很尴尬,就在几周前的noip中,有一个dalao给我们得瑟说他会线段树,千方百计地得瑟(虽然他考得并不好23333),然后羡慕的我们口水横流啊,今天才发现,线段树其实挺简单的,废话不多说,直接贴代码
#include <iostream>
using namespace std;
int st[11000],a[11000],sr[11000];
void build(int z,int l,int r)
{
if(l==r)
st[z]=a[l];
else
{
int mid=(l+r)/2;
build(z*2,l,mid);
build(z*2+1,mid+1,r); //注意mid+1,不要忘了加一
st[z]=max(st[z*2],st[z*2+1]); //本题,求最大值
}
}
void change(int z,int l,int r,int aim,int ans)
{
if(l==r&&l==aim)
{
st[z]=ans;
return;
}
int mid=(l+r)/2;
if(aim<=mid) //这里aim<=mid不解释
change(z*2,l,mid,aim,ans);
else
change(z*2+1,mid+1,r,aim,ans); //加1加1加1别忘了
st[z]=max(st[z*2],st[z*2+1]); //最大值
}
int find(int z,int wl,int wr,int l,int r) //wl想要的区间左节点,wr想要的区间右节点
{
if(wl>r||wr<l) //区间交叉,想要的区间不包含在正在搜寻的区间内
return -1; //返回一个无影响的值
if(wl<=l&&wr>=r)
return st[z];
int mid=(l+r)/2;
int le=find(z*2,wl,wr,l,mid),ri=find(z*2+1,wl,wr,mid+1,r); //二分查询最大值
return max(le,ri);
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if(x==2)
change(1,1,n,y,z);
if(x==1)
cout<<find(1,y,z,1,n);
}
return 0;
}
欢迎来顶