zoukankan      html  css  js  c++  java
  • hdu3308

    hdu3308 LCIS
    传送门
    题意
    给出一个(n(1leq nleq 100000))个数的序列,进行(m(1leq mleq 100000))次操作,每次操作修改一个数的值或者计算一段连续区间内最长递增子串的长度
    题解
    线段树区间合并
    每个节点维护三个变量:区间内最长递增子串的长度,从区间左端点开始的最长递增子串的长度,从区间右端点开始的最长递增子串的长度
    (pushup)函数中对三个变量分别进行修改
    最终结果会在左区间,右区间,跨越左右区间三者之一处取到

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<cmath>
    #include<ctime>
    #include<algorithm>
    #define LL long long
    #define PII pair<int,int>
    #define PLL pair<LL,LL>
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lowbit(x) x&(-x)
    using namespace std;
    
    const int maxn=100010;
    int T,n,m,a[maxn];
    char s[5];
    struct node{
        int amx,lmx,rmx;
    }tree[4*maxn];
    
    void pushup(int o,int l,int r){
        int mid=(l+r)>>1;
        tree[o].amx=max(tree[o<<1].amx,tree[o<<1|1].amx);
        if(a[mid]<a[mid+1]) tree[o].amx=max(tree[o].amx,tree[o<<1].rmx+tree[o<<1|1].lmx);
        tree[o].lmx=tree[o<<1].lmx;
        if(tree[o].lmx==mid-l+1 && a[mid]<a[mid+1]) tree[o].lmx+=tree[o<<1|1].lmx;
        tree[o].rmx=tree[o<<1|1].rmx;
        if(tree[o].rmx==r-mid && a[mid]<a[mid+1]) tree[o].rmx+=tree[o<<1].rmx;
    }
    
    void build(int o,int l,int r){
        if(l==r){
            tree[o].amx=tree[o].lmx=tree[o].rmx=1;
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        pushup(o,l,r);
    }
    
    void change(int o,int l,int r,int x,int v){
        if(l==r){
            a[l]=v;
            return;  
        }
        int mid=(l+r)>>1;
        if(x<=mid) change(o<<1,l,mid,x,v);
        else change(o<<1|1,mid+1,r,x,v);
        pushup(o,l,r);
    }
    
    int query(int o,int l,int r,int ql,int qr){
        if(ql<=l && r<=qr) return tree[o].amx;
        int mid=(l+r)>>1;
        int ans=0;
        //左区间最值
        if(ql<=mid) ans=max(ans,query(o<<1,l,mid,ql,qr));
        //右区间最值
        if(qr>mid) ans=max(ans,query(o<<1|1,mid+1,r,ql,qr));
        //跨越左右区间的最值
        if(ql<=mid && qr>mid && a[mid]<a[mid+1]){
            ans=max(ans,min(mid-ql+1,tree[o<<1].rmx)+min(qr-mid,tree[o<<1|1].lmx));
        }
        return ans;
    }
    
    int main(){
        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);
            while(m--){
                scanf("%s",s);
                if(s[0]=='U'){
                    int x,y;
                    scanf("%d %d",&x,&y);
                    x++;
                    change(1,1,n,x,y);
                }
                else{
                    int l,r;
                    scanf("%d %d",&l,&r);
                    l++;
                    r++;
                    printf("%d
    ",query(1,1,n,l,r));
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    2020牛客暑期多校训练营(第一场)I 1or 2题解
    5-23ACM训练题解(NWERC 2019)
    5-20ACM训练题解(2017-2018 ACM-ICPC Pacific Northwest Regional Contest)
    5-6ACM训练题解(2019 Russia Team Open Contest)
    5-2ACM训练题解(Asia Nakhon Pathom Regional Contest)
    4-30ACM训练题解(ICPC Asia Taipei-Hsinchu Contest)
    4-22ACM训练题解(ZOJ Monthly Jan 2019)
    「学习笔记」子序列自动机
    「学习笔记」后缀自动机
    「学习笔记」后缀数组
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13546075.html
Copyright © 2011-2022 走看看