hdu 3308 线段树

输入一串数字,有两个操作:Q a b 查询a到b区间内严格递增子串的最大长度 ; U a b 把第a位数字替换成b 。注意输入的编号是从0开始

解法:线段树维护区间的严格递增子串的最大长度即可。注意细节。

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

using namespace std;
struct Tree{
    int l,r;
    int valuel,valuer,value;
    int ld,rd;

}nod[100020<<2];
int n,m;
int w[1000020] ;

void Pushup(int k)
{
    nod[k].valuel = nod[k].valuer = 1;
    if(nod[k<<1].rd < nod[k<<1|1].ld){
        nod[k].value=max(nod[k<<1].valuer+nod[k<<1|1].valuel,
                         max(nod[k<<1].value,nod[k<<1|1].value));
        if(nod[k<<1].valuel == nod[k<<1].r-nod[k<<1].l+1 ){
            nod[k].valuel=nod[k<<1].valuel+nod[k<<1|1].valuel ;
        }
        if(nod[k<<1|1].valuer == nod[k<<1|1].r-nod[k<<1|1].l+1){
            nod[k].valuer=nod[k<<1|1].valuer+nod[k<<1].valuer;
        }
        nod[k].valuel=max(nod[k].valuel,nod[k<<1].valuel) ;
        nod[k].valuer=max(nod[k].valuer,nod[k<<1|1].valuer) ;
        //cout<<nod[2].valuer<<endl;
    }
    else{
        nod[k].value=max(nod[k<<1].value,nod[k<<1|1].value) ;
        nod[k].valuel = nod[k<<1].valuel ;
        nod[k].valuer = nod[k<<1|1].valuer ;
    }
    nod[k].ld=nod[k<<1].ld , nod[k].rd=nod[k<<1|1].rd ;
}

void Build(int l,int r,int k)
{
    nod[k].l=l,nod[k].r=r , nod[k].ld=w[nod[k].l] , nod[k].rd=w[nod[k].r] ;
    if(nod[k].l == nod[k].r){
        nod[k].value= nod[k].valuel =nod[k].valuer= 1;
        return ;
    }
    int mid = (l+r)>>1 ;
    Build(l,mid,k<<1);
    Pushup(k) ;
    Build(mid+1,r,k<<1|1);
    Pushup(k);
}

int Query(int l,int r,int k)
{
    int ans =0;
    if(nod[k].l==l && nod[k].r==r ){
        return nod[k].value ;
    }
    int mid=(nod[k].l + nod[k].r)>>1 ;
    if(r<=mid){
        return Query(l,r,k<<1) ;
    }
    else if(l>mid){
        return Query(l,r,k<<1|1) ;
    }
    else{
        if(nod[k<<1].rd < nod[k<<1|1].ld  ){
            ans = max(Query(l,mid,k<<1) , Query(mid+1,r,k<<1|1)) ;
            int temp = min(mid-l+1,nod[k<<1].valuer)+min(r-(mid+1)+1,nod[k<<1|1].valuel) ;
            ans=max(ans,temp);
         }
         else{
            ans= max(Query(l,mid,k<<1),Query(mid+1,r,k<<1|1)) ;
         }

    }
    return ans ;

}

void Update(int l,int k,int value)
{
    if(nod[k].l==nod[k].r && nod[k].l == l){
        nod[k].ld = nod[k].rd = value ;
        w[nod[k].r]=value ;
        nod[k].valuel = nod[k].valuer = nod[k].value =1 ;

        return ;
    }
    int mid=(nod[k].l+ nod[k].r)>>1 ;
    if(l<=mid){
        Update(l,k<<1,value);
    }
    else{
        Update(l,k<<1|1,value) ;
    }
    Pushup(k);
    return ;

}
int main()
{
    int t;
    scanf("%d",&t) ;
    while(t--){
        scanf("%d%d",&n,&m) ;
        memset(w,0,sizeof w) ;
        for(int i=1;i<=n;i++){
            scanf("%d",&w[i]) ;
        }
        //getchar() ;

        Build(1,n,1) ;
        /*for(int i=1;i<=30;i++){
            cout<<i<<" "<<nod[i].value<<" "<<nod[i].valuel<<" "<<nod[i].valuer<<endl;
        }
        cout<<"-------------------------------------"<<endl;*/
        for(int i=0;i<m;i++){

            char c;
            int a,b;
            cin>>c;
            scanf("%d%d",&a,&b);
            //cout<<c<<endl;
            if(c==‘Q‘){
               a++,b++;
               if(a>b){
                swap(a,b) ;
               }
               int ans = Query(a,b,1);
               //cout<<c<<endl;
               printf("%d\n",ans) ;
            }
            else{
                a++;
                Update(a,1,b) ;
                /*for(int i=1;i<=30;i++){
                    cout<<i<<" "<<nod[i].value<<" "<<nod[i].valuel<<" "<<nod[i].valuer<<endl;
                }
                cout<<"-------------------------------------"<<endl;*/
            }
        }
    }
    return 0;
}
时间: 2024-07-30 12:29:30

hdu 3308 线段树的相关文章

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

HDU 3308 线段树(区间合并)

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3896    Accepted Submission(s): 1766 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

HDU 3308 线段树单点更新+区间查找最长连续子序列

LCIS                                                              Time Limit: 6000/2000 MS (Java/Others)                                                                 Memory Limit: 65536/32768 K (Java/Others)                                       

hdu 3308(线段树区间合并)

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6069    Accepted Submission(s): 2635 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

HDU 3308 线段树之区间合并

点击打开链接 题意:T组数据,每组n和m,代表n个数和m次操作,U代表将第a个数的值改为b,Q代表询问a~b区间的最长连续上升子序列的长度,严格上升的 思路:一看到询问多少次了这种,肯定是线段树不用想,问区间的最长上升,可以用区间合并,lnum代表从区间左第一个元素开始的最长上升长度,注意第一个元素必须有,rnum代表从区间必须有最后一个元素的最长上升子序列,,mmnum代表区间最长的上升子序列,而num现在存的并不是树了,而是数据,具体的还有注释 #include <stdio.h> #in

hdu 3308 线段树 区间合并+单点更新+区间查询

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6592    Accepted Submission(s): 2866 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

hdu 3308线段树 区域合并

区域合并时需要考虑两点 1.pushup中区域合并时最左右递增长度(llen/rlen)等于整个区域长度(r - l)时需要重新计算父区域的最左右的递增长度 2.query中需要考虑区域合并接口处是否有可能产生ans值 #include<iostream> #include<stdio.h> #include<string> #include<string.h> using namespace std; const int maxn = 100050; st

hdu 3308 线段树,单点更新 求最长连续上升序列长度

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9713    Accepted Submission(s): 4215 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro