线段树——区间合并 单点更新 模板

http://acm.hdu.edu.cn/showproblem.php?pid=3308

#include<algorithm>
#include<cstring>
#include<cstdio> 
#include<iostream>
using namespace std;
struct node{
    int ls,rs,ms;   //ls 区间左连续序列的长度 
};
node no[8*100000];
int a[8*100000];
void pushup(int cr,int l,int r){
    no[cr].ls=no[cr<<1].ls;       
    no[cr].rs=no[cr<<1|1].rs;
    no[cr].ms=max(no[cr<<1|1].ms,no[cr<<1].ms);;

    int mid=(l+r)/2;    
    if( no[cr].ls==mid-l+1 && a[mid]<a[mid+1]  ){ //区间左连续与 右子区间左连续 
        no[cr].ls+=no[cr<<1|1].ls; 
    }     
    if( no[cr].rs==r-mid && a[mid]<a[mid+1] ){  //区间右连续与 左子区间右连续 
        no[cr].rs+=no[cr<<1].rs; 
    }
    if(a[mid]<a[mid+1])
    no[cr].ms=max(no[cr].ms,no[cr<<1].rs+no[cr<<1|1].ls);
}

void build(int l,int r,int cr){
    if(l==r){
        no[cr].ls=no[cr].rs=no[cr].ms=1;
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,cr<<1);
    build(mid+1,r,cr<<1|1);
    pushup(cr,l,r);    
}

int query(int l,int r,int cr,int L,int R){
    if(l==L&&r==R){    
        return no[cr].ms;
    }
    int mid=(L+R)/2,ans=0;
    if( r<=mid ){                          //左边找 
        ans=query(l,r,cr<<1,L,mid);    
    }  
    else if(l>mid){                            //或右边找 
        ans=query(l,r,cr<<1|1,mid+1,R);
    }
    else {                //中间找 
		ans=max(query(l,mid,cr<<1,L,mid),query(mid+1,r,cr<<1|1,mid+1,R)); //左边最长,右边最长 
		if(a[mid]<a[mid+1])
			ans=max( min( no[cr<<1].rs, mid-l+1 )+min( no[cr<<1|1].ls,r-mid),ans); //中间最长 
    }
    return ans;                    
}
void update(int p,int val,int L,int R,int cr){
    if(L==p&&R==p){
        a[p]=val;
        return ;
    }
    int mid=(L+R)/2;
    if(p<=mid) update(p,val,L,mid,cr<<1);
    else update(p,val,mid+1,R,cr<<1|1); 
    pushup(cr,L,R);
}
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",&a[i]);
        }
        build(1,n,1);
        getchar();
        while(m--){
            char s[5];
            scanf("%s",s);
            if(s[0]=='U'){
                int b,c;
                scanf("%d%d",&b,&c);
                   update(b+1,c,1,n,1);
            }else {
                int b,c;
                scanf("%d%d",&b,&c);
                b++,c++;
                printf("%d\n",query(b,c,1,1,n));
            }
       }

    }
} 

  

posted @ 2018-08-07 17:14  bear_ge  阅读(129)  评论(0编辑  收藏  举报