uestc 1425 Another LCIS(成段更新)

题意:有T(t<10)组数据,给你N个数,M个操作(N和M都小于100000)。操作有两种类型,(1)“q a b”,查询区间[a,b]里的最长连续上升序列的长度。(2)“a l r v”,将区间[l,r]里的数全部增加v。

         要记录区间里的最长的序列长度是多少,用mx来记录。由于最长的连续上升序列可以在区间的左端点,右端点,所以在线段树里增加两个域lmx和rmx,分别表示,在区间的端点处,分别向右向左的最长的满足条件的序列长度。但是还有可能出现在中间,所以又增加两个域lval和rval,分别表示区间端点的值是多少。合并的时候,判断左儿子的rval是否小于右儿子lval,如果满足,这个区间的mx可能为左儿子的rmx加上右儿子的lmx。另外,这个区间的mx可能是左儿子的mx或者右儿子的mx。
        在更新当前区间的lmx时,如果左子区间的lmx等于左子区间的长度,那么当前区间的lmx就要加上右儿子的lmx。更新当前区间的rmx时同理。
        另外在查询的时候,要注意,有可能当前区间的lmx大于mid-st+1,所以要在其中取一个较小值,同理rmx有可能大于ed-mid。

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
#define LL(x) (x<<1)  
#define RR(x) (x<<1|1)  
#define MID(a,b) (a+((b-a)>>1))  
const int N=100005;  
struct node  
{  
    int lft,rht;  
    int lmx,rmx,mx;  
    int lval,rval,add;  
    void fun(int tmp)  
    { add+=tmp; lval+=tmp; rval+=tmp; }  
    int len(){return rht-lft+1;}  
    int mid(){return MID(lft,rht);}  
    void init(){ lmx=rmx=mx=add=0; }  
};  
  
int y[N],n,m;  
  
struct Segtree  
{  
    node tree[N*4];  
    void down(int ind)  
    {  
        if(tree[ind].add)  
        {  
            tree[LL(ind)].fun(tree[ind].add);  
            tree[RR(ind)].fun(tree[ind].add);  
            tree[ind].add=0;  
        }  
    }  
    void up(int ind)  
    {  
        tree[ind].lmx=tree[LL(ind)].lmx;  
        tree[ind].rmx=tree[RR(ind)].rmx;  
        tree[ind].lval=tree[LL(ind)].lval;  
        tree[ind].rval=tree[RR(ind)].rval;  
        tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);  
  
        if(tree[LL(ind)].rval<tree[RR(ind)].lval)  
        {  
            if(tree[LL(ind)].lmx==tree[LL(ind)].len())  
                tree[ind].lmx+=tree[RR(ind)].lmx;  
            if(tree[RR(ind)].rmx==tree[RR(ind)].len())  
                tree[ind].rmx+=tree[LL(ind)].rmx;  
            tree[ind].mx=max(tree[ind].mx,tree[LL(ind)].rmx+tree[RR(ind)].lmx);  
        }  
        tree[ind].mx=max(tree[ind].mx,max(tree[ind].lmx,tree[ind].rmx));  
    }  
    void build(int lft,int rht,int ind)  
    {  
        tree[ind].lft=lft;  tree[ind].rht=rht;  
        tree[ind].init();  
        if(lft==rht)  
        {  
            tree[ind].lval=tree[ind].rval=y[lft];  
            tree[ind].lmx=tree[ind].rmx=tree[ind].mx=1;  
        }  
        else  
        {  
            int mid=tree[ind].mid();  
            build(lft,mid,LL(ind));  
            build(mid+1,rht,RR(ind));  
            up(ind);  
        }  
    }  
    void updata(int st,int ed,int ind,int valu)  
    {  
        int lft=tree[ind].lft,rht=tree[ind].rht;  
        if(st<=lft&&rht<=ed) tree[ind].fun(valu);  
        else  
        {  
            down(ind);  
            int mid=tree[ind].mid();  
            if(st<=mid) updata(st,ed,LL(ind),valu);  
            if(ed> mid) updata(st,ed,RR(ind),valu);  
            up(ind);  
        }  
    }  
    int query(int st,int ed,int ind)  
    {  
        int lft=tree[ind].lft,rht=tree[ind].rht;  
        if(st<=lft&&rht<=ed) return tree[ind].mx;  
        else  
        {  
            down(ind);  
            int mid=tree[ind].mid();  
            if(ed<=mid) return query(st,ed,LL(ind));  
            else if(st>mid) return query(st,ed,RR(ind));  
            else  
            {  
                int mid=tree[ind].mid();  
                int mx1=query(st,ed,LL(ind));  
                int mx2=query(st,ed,RR(ind));  
                int tmp1=0,tmp2=0;  
                if(tree[LL(ind)].rval<tree[RR(ind)].lval)  
                {  
                    tmp1=min(mid-st+1,tree[LL(ind)].rmx);  
                    tmp2=min(ed-mid,tree[RR(ind)].lmx);  
                }  
                return max(max(mx1,mx2),tmp1+tmp2);  
            }  
        }  
    }  
}seg;  
int main()  
{  
    int t,t_cnt=0;  
    scanf("%d",&t);  
    while(t--)  
    {  
        char str[10];  
        int a,b,c;  
  
        scanf("%d%d",&n,&m);  
        for(int i=1;i<=n;i++) scanf("%d",&y[i]);  
        seg.build(1,n,1);  
  
        printf("Case #%d:\n",++t_cnt);  
        while(m--)  
        {  
            scanf("%s",str);  
            if(str[0]=='q')  
            {  
                scanf("%d%d",&a,&b);  
                printf("%d\n",seg.query(a,b,1));  
            }  
            else  
            {  
                scanf("%d%d%d",&a,&b,&c);  
                seg.updata(a,b,1,c);  
            }  
        }  
    }  
    return 0;  
}  


你可能感兴趣的:(uestc 1425 Another LCIS(成段更新))