【常用模板】 线段树单点操作

来源:互联网 发布:php字符串截取添加 编辑:程序博客网 时间:2024/06/08 10:56

输入
第一行两个整数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;} 

欢迎来顶

0 0
原创粉丝点击