hdu 3308

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

线段树,区间合并的入门题啊。蛮好的。更新直接更新到底,查询注意。合并的情况。这个地方错了2次。

下面是AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100000+100;
int a[maxn];
struct node{
    int l,r;
    int msum,lsum,rsum,lv,rv;
}T[maxn<<2];
void pushup(int id,int l,int r){
     int m=(l+r)>>1;
     T[id].lv=T[id<<1].lv; T[id].rv=T[id<<1|1].rv;
     T[id].msum=max(T[id<<1].msum,T[id<<1|1].msum);
     if(T[id<<1].rv<T[id<<1|1].lv){
       T[id].msum=max(T[id].msum,T[id<<1].rsum+T[id<<1|1].lsum);
     }
     T[id].lsum=T[id<<1].lsum;
     T[id].rsum=T[id<<1|1].rsum;
     if(T[id<<1].lsum==m-l+1&&T[id<<1].rv<T[id<<1|1].lv){
        T[id].lsum+=T[id<<1|1].lsum;
     }
     if(T[id<<1|1].rsum==r-m&&T[id<<1].rv<T[id<<1|1].lv){
        T[id].rsum+=T[id<<1].rsum;
     }
}
void build(int id,int l,int r){
    T[id].l=l;T[id].r=r;
    if(l==r) {
        T[id].lv=T[id].rv=a[l];
        T[id].msum=T[id].lsum=T[id].rsum=1;
        return;
    }
    int m=(l+r)>>1;
    build(id<<1,l,m);  build(id<<1|1,m+1,r);
    pushup(id,l,r);
}
void update(int id,int l,int val){
      if(T[id].l==l&&T[id].r==l){
        T[id].lv=T[id].rv=val;
        T[id].msum=T[id].lsum=T[id].rsum=1;
        return;
      }
      int m=(T[id].l+T[id].r)>>1;
      if(m>=l) update(id<<1,l,val);
      else     update(id<<1|1,l,val);
      pushup(id,T[id].l,T[id].r);
}
int query(int id,int l,int r){
    if(T[id].l==l&&T[id].r==r){
       return T[id].msum;
    }
    int m=(T[id].l+T[id].r)>>1;
    if(m>=r){
       return  query(id<<1,l,r);
    }
    else if(l>m){
       return  query(id<<1|1,l,r);
    }
    else{
       int a=query(id<<1,l,m);

       int b=query(id<<1|1,m+1,r);

       if(T[id<<1].rv<T[id<<1|1].lv){
           int lsum=min(T[id<<1].rsum,m-l+1); int rsum=min(T[id<<1|1].lsum,r-m);
          return max(a,max(lsum+rsum,b));
       }
       else{
         return  max(a,b);
       }
    }
}
int main(){
    int t,n,m,l,r;  char str[200];
    scanf("%d",&t);
    while(t--){
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
       build(1,1,n);
       for(int i=0;i<m;i++){
           scanf("%s%d%d",str,&l,&r);
           if(str[0]=='Q'){
               l++;r++;
               printf("%d\n",query(1,l,r));
           }
           else{
               l++; update(1,l,r);
           }
       }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值