线段树代码整理

·      单点更新:最最基础的线段树,只更新叶子节点,然后把信息用PushUP(int r)这个函数更新上来

o   hdu1166敌兵布阵
题意:O(-1)
思路:O(-1)
线段树功能:update:单点增减 query:区间求和

/*************************************************************************
	> File Name: hdu1166.cpp
	> Author: FangPin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 六  3/ 5 22:07:17 2016
 ************************************************************************/

#include<iostream>
using namespace std;

class SegmentTree{
private:
    int *a;
    void pushup(int rt){
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
public:
    SegmentTree(int n){
        a=new int[n<<2];
    }
    ~SegmentTree(){
        delete[] a;
    }

    void build(int rt,int l,int r){
        if(l==r){
            scanf("%d",&a[rt]);
            return ;
        }
        else{
            int m=(l+r)>>1;
            build(rt<<1,l,m);
            build(rt<<1|1,m+1,r);
            pushup(rt);
        }
    }

    void update(int rt,int l,int r,int pos,int val){
        if(l==r){
            a[rt]+=val;
            return;
        }
        int m=(l+r)>>1;
        if(m>=pos)
            update(rt<<1,l,m,pos,val);
        else
            update(rt<<1|1,m+1,r,pos,val);
        pushup(rt);
    }

    int query(int rt,int l,int r,int x,int y){
        if(x<=l && y>=r)
            return a[rt];
        int ans=0;
        int m=(l+r)>>1;
        if(x<=m)
            ans+=query(rt<<1,l,m,x,y);
        if(y>m)
            ans+=query(rt<<1|1,m+1,r,x,y);
        return ans;
    }
};

int main(){
    int t;
    scanf("%d",&t);
    for(int ca=0;ca<t;++ca){
        int n;
        scanf("%d",&n);
        SegmentTree sum(n);
        sum.build(1,1,n);
        printf("Case %d:\n",ca+1);
        char s[10];
        while(scanf("%s",s),s[0]!='E'){
            if(s[0]=='Q'){
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d\n",sum.query(1,1,n,x,y));
            }
            else{
                int pos,val;
                scanf("%d%d",&pos,&val);
                if(s[0]=='S')
                    val=-val;
                sum.update(1,1,n,pos,val);
            }
        }
    }
}

o   hdu1754 I Hate It
题意:O(-1)
思路:O(-1)
线段树功能:update:单点替换 query:区间最值

/*************************************************************************
	> File Name: hdu1754.cpp
	> Author: FangPin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 日  3/ 6 21:24:47 2016
 ************************************************************************/

#include<iostream>
#include <algorithm>
#include <cstdio>
using namespace std;

class SegmentTree{
private:
    int *a;
    void pushup(int rt){
        a[rt]=max(a[rt<<1],a[rt<<1|1]);
    }
public:
    SegmentTree(int n){
        a=new int[n<<2];
    }
    ~SegmentTree(){
        delete[] a;
    }

    void build(int rt,int l,int r){
        if(l==r){
            scanf("%d",a+rt);
            return;
        }
        int m=(l+r)>>1;
        build(rt<<1,l,m);
        build(rt<<1|1,m+1,r);
        pushup(rt);
    }

    void update(int rt,int l,int r,int pos,int val){
        if(l==r){
            a[rt]=val;
            return ;
        }
        int m=(l+r)>>1;
        if(m>=pos)
            update(rt<<1,l,m,pos,val);
        else
            update(rt<<1|1,m+1,r,pos,val);
        pushup(rt);
    }

    int query(int rt,int l,int r,int x,int y){
        if(x<=l && y>=r)
            return a[rt];
        int m=(l+r)>>1;
        int ans=-(1<<30);
        if(x<=m)
            ans=max(ans,query(rt<<1,l,m,x,y));
        if(y>m)
            ans=max(ans,query(rt<<1|1,m+1,r,x,y));
        return ans;
    }
};

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        SegmentTree st(n);
        st.build(1,1,n);
        char s[3];
        int a,b;
        for(int i=0;i<m;++i){
            scanf("%s%d%d",s,&a,&b);
            if(s[0]=='Q')
                printf("%d\n",st.query(1,1,n,a,b));
            else st.update(1,1,n,a,b);
        }
    }
    return 0;
}

o   hdu1394 Minimum Inversion Number
题意:求Inversion后的最小逆序数
思路:用O(nlogn)复杂度求出最初逆序数后,就可以用O(1)的复杂度分别递推出其他解
线段树功能:update:单点增减 query:区间求和

/*************************************************************************
	> File Name: hdu1394.cpp
	> Author: FangPin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 日  3/ 6 21:58:42 2016
 ************************************************************************/

#include<iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

class SegmentTree{
private:
    int *a;
    void pushup(int rt){
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
public:
    SegmentTree(int n){
        a=new int[n<<2];
        memset(a,0,(n<<2)*sizeof(int));
    }
    ~SegmentTree(){
        delete[] a;
    }
    void update(int rt,int l,int r,int pos){
        if(l==r){
            ++a[rt];
            return;
        }
        int m=(l+r)>>1;
        if(m>=pos)
            update(rt<<1,l,m,pos);
        else update(rt<<1|1,m+1,r,pos);
        pushup(rt);
    }
    int query(int rt,int l,int r,int x,int y){
        if(x<=l && y>=r)
            return a[rt];
        int m=(l+r)>>1;
        int ans=0;
        if(m>=x)
            ans+=query(rt<<1,l,m,x,y);
        if(y>m)
            ans+=query(rt<<1|1,m+1,r,x,y);
        return ans;
    }
};

int data[5002];

int main(){
    int n;
    while(~scanf("%d",&n)){
        SegmentTree st(n);
        int ret=0;
        for(int i=1;i<=n;++i){
            scanf("%d",data+i);
            ++data[i];
            st.update(1,1,n,data[i]);
            ret+=st.query(1,1,n,data[i]+1,n);
        }
        int ans=ret;
        for(int i=1;i<n;++i){
            ret+=n+1-2*data[i];
            ans=min(ans,ret);
        }
        printf("%d\n",ans);
    }
}

o   hdu2795 Billboard
题意:h*w的木板,放进一些1*L的物品,求每次放空间能容纳且最上边的位子
思路:每次找到最大值的位子,然后减去L
线段树功能:query:区间求最大值的位子(直接把update的操作在query里做了)

/*************************************************************************
	> File Name: hdu2795.cpp
	> Author: FangPin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 一  3/ 7 22:09:59 2016
 ************************************************************************/

#include <cstdio>
#include<iostream>
#include <algorithm>
using namespace std;

class SegmentTree{
private:
    int *a;
    void pushup(int rt){
        a[rt]=max(a[rt<<1],a[rt<<1|1]);
    }
public:
    SegmentTree(int n,int w){
        a=new int[n<<2];
        for(int i=1;i<(n<<2);++i)
            a[i]=w;
    }
    ~SegmentTree(){
        delete[] a;
    }
    int query(int rt,int l,int r,int w){
        if(l==r){
            a[rt]-=w;
            return l;
        }
        int m=(l+r)>>1;
        int ans=(a[rt<<1]>=w)?query(rt<<1,l,m,w):query(rt<<1|1,m+1,r,w);
        pushup(rt);
        return ans;
    }
    int all_max()const{
        return a[1];
    }
};

int main(){
    int h,w,n;
    while(scanf("%d%d%d",&h,&w,&n)==3){
        SegmentTree st(min(h,n),w);
        for(int i=0;i<n;++i){
            int x;
            scanf("%d",&x);
            if(st.all_max()<x) puts("-1");
            else printf("%d\n",st.query(1,1,min(h,n),x));
        }
    }

    return 0;
}
poj 2828
</pre><pre code_snippet_id="1598774" snippet_file_name="blog_20160307_4_4006020" name="code" class="cpp">

/*************************************************************************
	> File Name: poj2828.cpp
	> Author: Fang Pin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 2016年03月09日 星期三 22时01分29秒
 ************************************************************************/

#include<iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

class SegmentTree{
private:
    int *a,*b;
    void pushup(int rt){
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
public:
    SegmentTree(int n){
        a=new int[n<<2];
        b=new int[n];
    }
    ~SegmentTree(){
        delete[] a;
    }
    void build(int rt,int l,int r){
        if(l==r){
            a[rt]=1;
            return ;
        }
        int m=(l+r)>>1;
        build(rt<<1,l,m);
        build(rt<<1|1,m+1,r);
        pushup(rt);
    }
    void update(int rt,int l,int r,int pos,int val){
        if(l==r){
            a[rt]=0;
            b[l]=val;
            return;
        }
        int m=(l+r)>>1;
        if(a[rt<<1]>=pos)
            update(rt<<1,l,m,pos,val);
        else
            update(rt<<1|1,m+1,r,pos-a[rt<<1],val);
        pushup(rt);
    }
    int getans(int pos)const{
        return b[pos];
    }
};

int b[200002],data[200002][2];

int main(){
    int t;
    while(~scanf("%d",&t)){
        SegmentTree st(t);
        st.build(1,1,t);
        for(int i=1;i<=t;++i)
            scanf("%d%d",&data[i][0],&data[i][1]);
        for(int i=t;i>0;--i)
            st.update(1,1,t,data[i][0]+1,data[i][1]);
        for(int i=1;i<t;++i)
            printf("%d ",st.getans(i));
        printf("%d\n",st.getans(t));
    }
    return 0;
}


·      成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候

o   hdu1698 Just a Hook
题意:O(-1)
思路:O(-1)
线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)


/*************************************************************************
	> File Name: hdu1698.cpp
	> Author: Fang Pin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 2016年03月11日 星期五 22时06分04秒
 ************************************************************************/

#include<iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

class SegmentTree{
private:
    int *a;
    int *lazy;
    void pushup(int rt){
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
    void pushdown(int rt,int len){
        if(lazy[rt]){
            lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
            a[rt<<1]=(len-(len>>1))*lazy[rt];
            a[rt<<1|1]=(len>>1)*lazy[rt];
            lazy[rt]=0;
        }
    }
public:
    SegmentTree(int n){
        a=new int[n<<2];
        lazy=new int[n<<2];
        fill(lazy,lazy+(n<<2),0);
    }
    ~SegmentTree(){
        delete []a;
        delete []lazy;
    }
    void build(int rt,int l,int r){
        if(l==r){
            a[rt]=1;
            return ;
        }
        int m=(l+r)>>1;
        build(rt<<1,l,m);
        build(rt<<1|1,m+1,r);
        pushup(rt);
    }
    void update(int rt,int l,int r,int x,int y,int val){
        if(x<=l && y>=r){
            lazy[rt]=val;
            a[rt]=(r-l+1)*val;
            return;
        }
        pushdown(rt,r-l+1);
        int m=(l+r)>>1;
        if(x<=m)
            update(rt<<1,l,m,x,y,val);
        if(y>m)
            update(rt<<1|1,m+1,r,x,y,val);
        pushup(rt);
    }
    int ans()const{
        return a[1];
    }
};

int main(){
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;++ca){
        int n,m;
        scanf("%d%d",&n,&m);
        SegmentTree st(n);
        st.build(1,1,n);
        for(int i=0;i<m;++i){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            st.update(1,1,n,a,b,c);
        }
        printf("Case %d: The total value of the hook is %d.\n",ca,st.ans());
    }
    return 0;
}


o   poj3468 A Simple Problem with Integers
题意:O(-1)
思路:O(-1)
线段树功能:update:成段增减 query:区间求和


/*************************************************************************
	> File Name: poj3468.cpp
	> Author: Fang Pin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 日  3/13 23:16:31 2016
 ************************************************************************/

#include<iostream>
#include <cstdio>
#include <cstring>

using namespace std;

class SegmentTree{
private:
    long long *a,*lazy;
    void pushup(int rt){
        a[rt]=a[rt<<1]+a[rt<<1|1];
    }
    void pushdown(int rt,int len){
        if(lazy[rt]){
            lazy[rt<<1]+=lazy[rt];
            lazy[rt<<1|1]+=lazy[rt];
            a[rt<<1]+=(len-(len>>1))*lazy[rt];
            a[rt<<1|1]+=(len>>1)*lazy[rt];
            lazy[rt]=0;
        }
    }

public:
    SegmentTree(int n){
        a=new long long[n<<2];
        lazy=new long long[n<<2];
        memset(lazy,0,(n<<2)*sizeof(long long));
    }
    ~SegmentTree(){
        delete[] a;
        delete[] lazy;
    }
    void build(int rt,int l,int r){
        if(l==r){
            scanf("%lld",&a[rt]);
            return ;
        }
        int m=(l+r)>>1;
        build(rt<<1,l,m);
        build(rt<<1|1,m+1,r);
        pushup(rt);
    }
    void update(int rt,int l,int r,int x,int y,long long val){
        if(x<=l && y>=r){
            lazy[rt]+=val;
            a[rt]+=(r-l+1)*val;
            return;
        }
        int m=(l+r)>>1;
        pushdown( rt, r-l+1);
        if(x<=m)
            update(rt<<1,l,m,x,y,val);
        if(y>m)
            update(rt<<1|1,m+1,r,x,y,val);
        pushup(rt);
    }
    long long query(int rt,int l,int r,int x,int y){
        if(x<=l && y>=r)
            return a[rt];
        pushdown(rt,r-l+1);
        int m=(l+r)>>1;
        long long ans=0;
        if(x<=m)
            ans+=query(rt<<1,l,m,x,y);
        if(y>m)
            ans+=query(rt<<1|1,m+1,r,x,y);
        return ans;
    }
};

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    SegmentTree st(n);
    st.build(1,1,n);
    while(m--){
        char s[3];
        scanf("%s",s);
        if(s[0]=='Q'){
            int a,b;
            scanf("%d%d",&a,&b);
            printf("%lld\n",st.query(1,1,n,a,b));
        }
        else{
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            st.update(1,1,n,a,b,c);
        }
    }
    return 0;
}


  1. 对y轴进行建树,对每条线段按横轴从小到大排序,从第1条线段开始查询并更新 
  2. 查询该条线段所表示的区间内不同颜色数量(即可见线段数)并且记录可见线段,然后更新该区间颜色  
  3. 最后暴力求两两可见线段数量 
  4. 但是注意:0,4,1 和 0,2,2 和 3,4,2这三条线段覆盖的结果是区间0~4通过线段树查找可见线段是两条,其实是3条(2~3可见另一条) 
  5. 可以把查询更新的区间*2,比如上面数据变成0,8,1 和 0,4,2 和 6,8,2则4~6之间可见一条线段  



/*************************************************************************
	> File Name: 1436.cpp
	> Author: Fang Pin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 五  3/18 21:57:58 2016
 ************************************************************************/

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int MAXN=8005;

struct Node{
    int y1,y2,x;
}data[MAXN];

//bool hash[MAXN];
int lazy[MAXN<<3];
bool lk[MAXN][MAXN];

void build(){
    memset(lazy,0,sizeof(lazy));
}

void pushdown(int rt){
    if(lazy[rt]){
        lazy[rt<<1]=lazy[rt];
        lazy[rt<<1|1]=lazy[rt];
        lazy[rt]=0;
    }
}

void update(int rt,int l,int r,int x,int y,int val){
    if(x<=l && y>=r){
        lazy[rt]=val;
        return ;
    }
    int m=(l+r)>>1;
    pushdown(rt);
    if(x<=m)
        update(rt<<1,l,m,x,y,val);
    if(y>m)
        update(rt<<1|1,m+1,r,x,y,val);
}

void query(int rt,int l,int r,int x,int y,int pos){
    if(lazy[rt]){
        lk[lazy[rt]][pos]=true;
        return;
    }
    if(l==r)
        return ;
    int m=(l+r)>>1;
    pushdown(rt);
    if(x<=m)
        query(rt<<1,l,m,x,y,pos);
    if(y>m)
        query(rt<<1|1,m+1,r,x,y,pos);
}

void init(){
    memset(lk,false,sizeof(lk));
}

bool cmp(const Node &a,const Node &b){
    return a.x<b.x;
}


int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        init();
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%d%d%d",&data[i].y1,&data[i].y2,&data[i].x);
            if(data[i].y1>data[i].y2)
                swap(data[i].y1,data[i].y2);
            data[i].y1*=2;
            data[i].y2*=2;
        }
        sort(data,data+n,cmp);
        build();
        for(int i=0;i<n;++i){
            query(1,1,MAXN<<1,data[i].y1,data[i].y2,i+1);
            update(1,1,MAXN<<1,data[i].y1,data[i].y2,i+1);
        }
        int ans=0;
       //. debug(n);
        for(int i=1;i<=n;++i){
            for(int j=i+1;j<=n;++j){
                if(lk[i][j])
                    for(int k=j+1;k<=n;++k){
                        if(lk[i][k] && lk[j][k])
                            ++ans;
                    }
            }
        }
        printf("%d\n",ans);
    }
}

·      区间合并
这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并

o   poj3667 Hotel
题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间
线段树操作:update:区间替换 query:询问满足条件的最左断点


/*************************************************************************
> File Name: poj3667.cpp
> Author: Fang Pin
> Mail: fangpin1993@hotmail.com
> Created Time: 四  3/24 22:20:43 2016
************************************************************************/

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=55555;
int sum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2],lazy[MAXN<<2];
void pushup(int rt,int len){
    lsum[rt]=(lsum[rt<<1]==len-(len>>1))?lsum[rt<<1]+lsum[rt<<1|1]:lsum[rt<<1];
    rsum[rt]=(rsum[rt<<1|1]==(len>>1))?rsum[rt<<1|1]+rsum[rt<<1]:rsum[rt<<1|1];
    sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
}

void build(int rt,int l,int r){
    sum[rt]=lsum[rt]=rsum[rt]=r-l+1;
    lazy[rt]=-1;
    if(l==r)
    return;
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}


void pushdown(int rt,int m){
 	if (lazy[rt] != -1) {
		lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
		sum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = lazy[rt] ? 0 : m - (m >> 1);
		sum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = lazy[rt] ? 0 : (m >> 1);
		lazy[rt] = -1;
	}
}
int query(int rt,int l,int r,int x){
    if(l==r) return l;
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(sum[rt<<1]>=x) return query(rt<<1,l,m,x);
    else if(rsum[rt<<1]+lsum[rt<<1|1]>=x) return m-rsum[rt<<1]+1;
    else return query(rt<<1|1,m+1,r,x);
}

void update(int rt,int l,int r,int x,int y,int val){
    if(x<=l && y>=r){
        lazy[rt]=val;
        sum[rt]=lsum[rt]=rsum[rt]=val?0:r-l+1;
        return;
    }
    pushdown(rt,r-l+1);
    int m=(r+l)>>1;
    if(x<=m)
    update(rt<<1,l,m,x,y,val);
    if(y>m)
    update(rt<<1|1,m+1,r,x,y,val);
    pushup(rt,r-l+1);
}

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        build(1,1,n);
        for(int i=0;i<m;++i){
            int op,x,y;
            scanf("%d",&op);
            if(op==1){
                scanf("%d",&x);
                if(sum[1]<x) puts("0");
                else{
                    int ans=query(1,1,n,x);
                    printf("%d\n",ans);
                    update(1,1,n,ans,ans+x-1,1);
                }
            }
            else{
                scanf("%d%d",&x,&y);
                update(1,1,n,x,x+y-1,0);
            }
        }
    }
    return 0;
}



HDU3308-LCIS-线段树区间合并

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308

题目大意:给n个数,两种操作

                  1:U  a,b   更新第a个为b (从0开始)

                  2:Q  a,b  查询 a,b之间LCIS(最长连续递增子序列)的长度。

其实也可以说是个模板题;三个变量保存数据ls,rs,ms分别保存从左端点开始的最长连续上升子序列,从右端点开始的最长连续上升子序列,以及这个区间的最长连续上升子序列;唯一不同的就是这里得判断一下是否能够合并;即增加一个比较如果num[mid]<num[mid+1](num数组保存的是输入的数据


/*************************************************************************
	> File Name: hdu3308.cpp
	> Author: Fang Pin
	> Mail: fangpin1993@hotmail.com
	> Created Time: 日  3/27 21:47:12 2016
 ************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=100002;
int data[MAXN];
int a[MAXN<<2],la[MAXN<<2],ra[MAXN<<2];

void pushup(int rt,int l,int r){
    int m=(l+r)>>1;
    la[rt]=la[rt<<1];
    if(la[rt]==m-l+1 && data[m]<data[m+1])
        la[rt]+=la[rt<<1|1];
    ra[rt]=ra[rt<<1|1];
    if(ra[rt]==r-m && data[m]<data[m+1])
        ra[rt]+=ra[rt<<1];
    a[rt]=max(a[rt<<1],a[rt<<1|1]);
    if(data[m]<data[m+1])
    	a[rt]=max(a[rt],ra[rt<<1]+la[rt<<1|1]);
}


void build(int rt,int l,int r){
    if(l==r){
        a[rt]=la[rt]=ra[rt]=1;
        return;
    }
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    pushup(rt,l,r);
}

void update(int rt,int l,int r,int pos){
    if(l==r){
        return ;
    }
    int m=(l+r)>>1;
    if(pos<=m)
        update(rt<<1,l,m,pos);
    else if(pos>m)
        update(rt<<1|1,m+1,r,pos);
    pushup(rt,l,r);
}

int query(int rt,int l,int r,int x,int y){
    if(x<=l && y>=r){
        return a[rt];
    }
    int m=(l+r)>>1;
    int ans=0;
    if(x<=m)
        ans=max(ans,query(rt<<1,l,m,x,y));
    if(y>m)
        ans=max(ans,query(rt<<1|1,m+1,r,x,y));
    if(x<=m && y>m && data[m]<data[m+1])
        ans=max(ans,min(m-x+1,ra[rt<<1])+min(y-m,la[rt<<1|1]));
    return ans;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%d",&data[i]);
        }
        build(1,1,n);
        char s[10];
        int x,y;
        for(int i=0;i<m;++i){
            scanf("%s%d%d",s,&x,&y);
            if(s[0]=='Q'){
                printf("%d\n",query(1,1,n,x+1,y+1));
            }
            else{
                data[x+1]=y;
                update(1,1,n,x+1);
            }
        }
    }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值