zoukankan      html  css  js  c++  java
  • hdu 3308-线段树基本区间合并

    这题明显是线段树基本区间合并,由于第一次写也遇到了不少问题,下面将赘述。。

    首先对于区间合并问题,tr里面要有rsum,lsum,msum,分别表示左连续最大,右连续最大,和区间最大,为什么这么表示,当然是为了合并操作。

    先说pushup部分,不是简单的sum或者max了,按套路来,如果合并有特殊条件要加特殊条件,对于这道题要加判断arr[mi]和arr[mi+1],

    由于这道题没有pushdown,所以还算简单,下一步打算做一个有pushdown的,

    queue里面也有技巧,就是当mid在s和t中间时要用min确保合并的时候(当然是符合合并条件时)得到正确答案,以防多算了不在s和t中间的。

    midify就是简单的midify加pushup就可以了显而易见。

    由于是第一道区间合并还有理解不透彻的地方,希望继续努力,蒟蒻加油。。。

    #include<stdio.h>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int MAX=1000000;
    struct pr {
        int msum,lsum,rsum;
        int left,right;                    
    }tr[MAX+10];
    int n;
    inline int ll(int k) {return 2*k;}          //左边的下标
    inline int rr(int k) {return 2*k+1;}         //右边的下标
    inline int mid(int kk1,int kk2) {return (kk1+kk2)>>1;}
    int arr[MAX];
    
    void pushup(int k){//m=r-l+1;
        int l=tr[k].left,r=tr[k].right;
        int mi=mid(l,r);
        tr[k].lsum =tr[ll(k)].lsum;
        tr[k].rsum =tr[rr(k)].rsum;//如果合并有条件则加条件
        if(arr[mi]<arr[mi+1]){
            if (tr[k].lsum == mi-l+1) tr[k].lsum+=tr[rr(k)].lsum;
            if (tr[k].rsum == r-mi) tr[k].rsum+=tr[ll(k)].rsum;
            tr[k].msum = max(tr[rr(k)].lsum+tr[ll(k)].rsum,max(tr[ll(k)].msum,tr[rr(k)].msum));
            return;
        }
        tr[k].msum = max(tr[ll(k)].msum,tr[rr(k)].msum);
    }
    
    void build(int k,int s,int t) {
        tr[k].left=s;tr[k].right=t;
        if(s==t) {tr[k].lsum=tr[k].rsum=tr[k].msum=1;return;}               
        build(ll(k),s,mid(s,t));
        build(rr(k),mid(s,t)+1,t);
        pushup(k);    //pushup
        return;
    }
    
    void modify(int k,int s,int x) {
        int l=tr[k].left,r=tr[k].right;
        if(l==r){
            arr[s]=x;
            return ;
        }
        int mi=mid(l,r);
        if(s<=mi) modify(ll(k),s,x);
        else if(s>mi) modify(rr(k),s,x);
        pushup(k);
    }
    int query(int k,int s,int t) {
        int l=tr[k].left,r=tr[k].right;
        if(l==s&&r==t) return tr[k].msum;
        int mi=mid(l,r);
        int res=0;
        if (t<=mi) res=query(ll(k),s,t);
        else if(s>mi) res=query(rr(k),s,t);
        else {
            res=max(query(ll(k),s,mi),query(rr(k),mi+1,t));
            if(arr[mi]<arr[mi+1]){
                res=max(res,min(mi-s+1,tr[ll(k)].rsum)+min(t-mi,tr[rr(k)].lsum));
            }
        }
        return res;
    }
    
    int main(){
    
        int t;
        cin>>t;
        int n,m;
        while(t--){
            memset(tr,0,sizeof(tr));
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++){
                scanf("%d",&arr[i]);
            }
            build(1,1,n);
            char c[2];
            int a,b;
            for(int i=0;i<m;i++){
                scanf("%s%d%d",c,&a,&b);
                if(c[0]=='Q'){
                    printf("%d
    ",query(1,a+1,b+1));
                }
                else{
                    modify(1,a+1,b);
                }
            }
        }
        return 0;
    }



  • 相关阅读:
    MongoDB+模板引擎 项目实例-学生档案管理
    MongoDB 增删改查命令速查
    MongoDB 数据库概述及环境搭建
    Flutter 升级
    TypeScript 快速上手及学习笔记
    Android ContentProvider 启动分析
    HTTP 报文格式简介
    深入浅出 HTTPS (详解版)
    从你输入网址,到看到网页——详解中间发生的过程
    TCP 三次握手和四次挥手图解(有限状态机)
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672588.html
Copyright © 2011-2022 走看看