hdu 3308LCIS 线段树 区间合并

做法:这里的区间合并要考虑左区间的最右值和右区间的最右值,看两个区间是否可以靠相合形成一个新序列

#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
const int LMT=100003;
int msum[LMT<<2],lsum[LMT<<2],rsum[LMT<<2],rnum[LMT<<2],lnum[LMT<<2];
inline int max(int a,int b)
{
    return a>b?a:b;
}
void init(void)
{
    memset(msum,0,sizeof(msum));
    memset(lsum,0,sizeof(lsum));
    memset(rsum,0,sizeof(rsum));
    memset(lnum,0,sizeof(lnum));
    memset(rnum,0,sizeof(rnum));
}
void pushup(int x,int len)
{
    lnum[x]=lnum[x<<1];rnum[x]=rnum[x<<1|1];
    lsum[x]=lsum[x<<1];rsum[x]=rsum[x<<1|1];
    if(lsum[x]==len-(len>>1)&&lnum[x<<1|1]>rnum[x<<1])
        lsum[x]+=lsum[x<<1|1];
    if(rsum[x]==len>>1&&lnum[x<<1|1]>rnum[x<<1])
        rsum[x]+=rsum[x<<1];
    msum[x]=max(msum[x<<1],msum[x<<1|1]);
    if(rnum[x<<1]<lnum[x<<1|1])
        msum[x]=max(msum[x],rsum[x<<1]+lsum[x<<1|1]);
}
void update(int op,int pos,int l,int r,int x)
{
    if(l==r)
    {
        lnum[x]=rnum[x]=op;
        msum[x]=lsum[x]=rsum[x]=1;
        return;
    }
    //if(pos==6)printf("%d %d %d\n",l,r,x);
    int m=(l+r)>>1;
   if(pos<=m)update(op,pos,left);
   if(pos>m)update(op,pos,right);
   pushup(x,r-l+1);
}
void query(int num[3],int sum[3],int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        num[0]=lnum[x];num[2]=rnum[x];
        sum[0]=lsum[x];
        sum[1]=msum[x];
        sum[2]=rsum[x];
        return;
    }
    int m=(l+r)>>1,nums[2][3],sums[2][3],len=r-l+1;
    memset(nums,0,sizeof(nums));
    memset(sums,0,sizeof(sums)); 
    //printf("%d %d %d\n",l,r,x);
    if(L<=m)query(nums[0],sums[0],L,R,left);
    if(R>m)query(nums[1],sums[1],L,R,right);
    num[0]=nums[0][0];num[2]=nums[1][2];
    sum[0]=sums[0][0];sum[2]=sums[1][2];
    if(sums[0][0]==len-(len>>1)&&nums[0][2]<nums[1][0])
        sum[0]+=sums[1][0];
    if(sums[1][2]==len>>1&&nums[0][2]<nums[1][0])
        sum[2]+=sums[0][2];
    sum[1]=max(sums[0][1],sums[1][1]);
    if(nums[0][2]<nums[1][0])
        sum[1]=max(sums[0][2]+sums[1][0],sum[1]);
}
int main(void)
{
    int T,n,i,x,l,r,m,sum[3],num[3];
    char ord;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
        {
            scanf("%d",&x);
            update(x,i,0,n-1,1);
        }
        while(m--)
        {
            ord=getchar();
            while(ord!='U'&&ord!='Q')ord=getchar();
               memset(sum,0,sizeof(sum));
            memset(num,0,sizeof(num));
              if(ord=='Q')
            {
                scanf("%d%d",&l,&r);
               query(num,sum,l,r,0,n-1,1);
               printf("%d\n",sum[1]);
            }
            else
            {
                scanf("%d%d",&l,&x);
                update(x,l,0,n-1,1);
            }
        }
    }
    return 0;
}


 

你可能感兴趣的:(hdu 3308LCIS 线段树 区间合并)