zoukankan      html  css  js  c++  java
  • HDU_3308_线段树_区间合并

    LCIS

    Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 6166    Accepted Submission(s): 2675


    Problem Description
    Given n integers.
    You have two operations:
    U A B: replace the Ath number by B. (index counting from 0)
    Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
     
    Input
    T in the first line, indicating the case number.
    Each case starts with two integers n , m(0<n,m<=105).
    The next line has n integers(0<=val<=105).
    The next m lines each has an operation:
    U A B(0<=A,n , 0<=B=105)
    OR
    Q A B(0<=A<=B< n).
     
    Output
    For each Q, output the answer.
     
    Sample Input
    1 10 10 7 7 3 3 5 9 9 8 1 8 Q 6 6 U 3 4 Q 0 1 Q 0 5 Q 4 7 Q 3 5 Q 0 2 Q 4 6 U 6 10 Q 0 9
     
    Sample Output
    1 1 4 2 3 1 2 5
     
    第一道区间合并的线段树。

    看了题解,从下午做到晚上。。。然而看网上说是一道简单的区间合并。。。桑心。。。

    给出序列,可单点更新,求最长连续递增子列的长度。

    每一段记录

    struct Node
    {
      int l,r,len;  //线段树中的左右端点,以及序列长度
      int ln,rn;   //这个线段上的序列左右端点
      int lm,rm,nm;   //包含左端点,包含右端点,整段的最长递增连续子列长度
    } tree[maxn<<2];

    一个序列(rt)中的最长连续递增子列的长度(nm)是 max(tree[rt<<1].nm,tree[rt<<1|1].nm)和满足tree[rt<<1].rn<tree[rt<<1|1].ln(左孩子的右端点小于右孩子的左端点)条件下的tree[rt<<1].rm+tree[rt<<1|1].lm中较大者。更新点后pushup和query就是用这个思想。

    第一波超时,是因为mid=(l+r)/2,用位运算更快,mid=(l+r)>>1

    之前查询函数写的有问题。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 100005
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    struct Node
    {
        int l,r,len;
        int ln,rn;
        int lm,rm,nm;
    } tree[maxn<<2];
    
    int num[100005];
    
    void pushup(int rt)
    {
        tree[rt].ln=tree[rt<<1].ln;
        tree[rt].rn=tree[rt<<1|1].rn;
        tree[rt].lm=tree[rt<<1].lm;
        tree[rt].rm=tree[rt<<1|1].rm;
        tree[rt].nm=max(tree[rt<<1].nm,tree[rt<<1|1].nm);
        if(tree[rt<<1].rn<tree[rt<<1|1].ln)
        {
            if(tree[rt].lm==tree[rt<<1].len)
                tree[rt].lm+=tree[rt<<1|1].lm;
            if(tree[rt].rm==tree[rt<<1|1].len)
                tree[rt].rm+=tree[rt<<1].rm;
            tree[rt].nm=max(tree[rt].nm,tree[rt<<1].rm+tree[rt<<1|1].lm);
        }
    }
    
    void build(int l,int r,int rt)
    {
        tree[rt].l=l;
        tree[rt].r=r;
        tree[rt].len=r-l+1;
        if(l==r)
        {
            tree[rt].lm=tree[rt].rm=tree[rt].nm=1;
            tree[rt].ln=tree[rt].rn=num[l];
            return;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int pos,int x,int l,int r,int rt)
    {
        if(l==pos&&r==pos)
        {
            tree[rt].ln=tree[rt].rn=x;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)
            update(pos,x,lson);
        else
            update(pos,x,rson);
        pushup(rt);
    }
    
    int query(int L,int R,int l,int r,int rt)
    {
        if(L==l&&r==R)
            return tree[rt].nm;
        int mid=(l+r)>>1;
        if(R<=mid)
            return query(L,R,lson);
        else if(L>mid)
            return query(L,R,rson);
        else
        {
            int ll=query(L,mid,lson),ans=0;
            int rr=query(mid+1,R,rson);
            if(tree[rt<<1].rn<tree[rt<<1|1].ln)
                ans=min(mid-L+1,tree[rt<<1].rm)+min(R-mid,tree[rt<<1|1].lm);
            return max(ans,max(ll,rr));
        }
    }
    /*
    int query(int l,int r,int i)//查询最大的LCIS
    {
        if(tree[i].l>=l && tree[i].r<=r)
        {
            return tree[i].nm;
        }
        int mid = (tree[i].l+tree[i].r)>>1,ans = 0;
        if(l<=mid)
            ans = max(ans,query(l,r,2*i));
        if(r>mid)
            ans = max(ans,query(l,r,2*i+1));
        if(tree[2*i].rn < tree[2*i+1].ln)
            ans = max(ans , min(mid-l+1,tree[2*i].rm)+min(r-mid,tree[2*i+1].lm));
        return ans;
    }*/
    
    int main()
    {
        int t,n,m;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1; i<=n; i++)
                scanf("%d",&num[i]);
            build(1,n,1);
            //cout<<tree[9].nm<<endl;
            //cout<<"*"<<endl;
    
            for(int i=0; i<m; i++)
            {
                char str[2];
                int a,b;
                scanf("%s%d%d",str,&a,&b);
                if(str[0]=='U')
                    update(a+1,b,1,n,1);
                else if(str[0]=='Q')
                    printf("%d
    ",query(a+1,b+1,1,n,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    VC++下封装ADO类以及使用方法
    MFC浅析(7) CWnd类虚函数的调用时机、缺省实现
    JavaScript原生数组函数
    C#4.0泛型的协变,逆变深入剖析
    《这就是搜索引擎:核心技术详解》总结
    栈和队列
    JS菜单条智能定位效果
    实现模型工厂,依赖注入以及格式配置
    Intellij IDEA 快捷键整理
    printf code
  • 原文地址:https://www.cnblogs.com/jasonlixuetao/p/5510626.html
Copyright © 2011-2022 走看看