hdu3308 线段树 区间合并

给n个数字 U表示第A个数改为B。A是从0开始。

Q输出最大的递增序列个数。

考虑左边,右边,和最大的。

#include<stdio.h>

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

#define maxn 100010

int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];

int num[maxn];

int max(int x,int y)

{

    return x>y?x:y;

}

int min(int x,int y)

{

    return x<y?x:y;

}

void pushup(int l,int r,int rt)

{

    int m=(l+r)/2;

    lsum[rt]=lsum[rt<<1];

    rsum[rt]=rsum[rt<<1|1];

    msum[rt]=max(msum[rt<<1],msum[rt<<1|1]);

    if(num[m]<num[m+1])

    {

        if(lsum[rt<<1]==m-l+1)

            lsum[rt]=lsum[rt<<1]+lsum[rt<<1|1];

        if(rsum[rt<<1|1]==r-m)

            rsum[rt]=rsum[rt<<1|1]+rsum[rt<<1];

        msum[rt]=max(msum[rt],lsum[rt<<1|1]+rsum[rt<<1]);

    }

}

void build(int l,int r,int rt)

{

    

    if(l==r)

    {

        lsum[rt]=rsum[rt]=msum[rt]=1;

        return;

    }

    int m=(l+r)/2;

    build(lson);

    build(rson);

    pushup(l,r,rt);

}

void updata(int p,int c,int l,int r,int rt)

{

    if(l==r)

    {

        num[l]=c;

        return ;

    }

    int m=(l+r)/2;

    if(m>=p)

        updata(p,c,lson);

    else updata(p,c,rson);

    pushup(l,r,rt);

}

int query(int L,int R,int l,int r,int rt)

{

    if(l>=L&&R>=r)

        return msum[rt];

    int ret=0;

    int m=(l+r)/2;

    if(m>=L)

        ret=max(ret,query(L,R,lson));

    if(R>m)

        ret=max(ret,query(L,R,rson));

    if(num[m]<num[m+1])

    {

        ret=max(ret,min(m-L+1,rsum[rt<<1])+min(R-m,lsum[rt<<1|1]));

    }

    return ret;

}

int main()

{

    int n,t,m,i;

    char s[10];

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        for(i=1;i<=n;i++)

            scanf("%d",&num[i]);

        build(1,n,1);

        int a,b;

        while(m--)

        {

            scanf("%s %d %d",s,&a,&b);

            if(s[0]=='U')

                updata(a+1,b,1,n,1);

            else if(s[0]=='Q')

                printf("%d\n",query(a+1,b+1,1,n,1));

        }

    }

}

 

你可能感兴趣的:(HDU)