hdu 3308(线段树)

线段树求区间最长连续上升

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int maxn=1e5+100;
int ll[maxn<<2],rr[maxn<<2];//左边的连续上升子序列长度和右边的连续上升子序列长度
int a[maxn];
int mx[maxn<<2];//最长连续上升子序列长度
int t,n,m;
void pushup(int l,int r,int rt)
{
    ll[rt]=ll[rt<<1];
    rr[rt]=rr[rt<<1|1];
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
    int mid=(l+r)>>1;
    if(a[mid]<a[mid+1])
    {
        int zz=rr[rt<<1]+ll[rt<<1|1];
       mx[rt]=max(mx[rt],zz);
       if(rr[rt<<1]==mid-l+1) ll[rt]=zz;
       if(ll[rt<<1|1]==r-mid) rr[rt]=zz;
    }
}
void build(int l,int r,int rt)
{
    ll[rt]=1;
    rr[rt]=1;
    mx[rt]=1;
    if(l==r)
    {
        scanf("%d",&a[l]);
        ll[rt]=1;
        rr[rt]=1;
        mx[rt]=1;
        return;
    }
     int mid=(l+r)>>1;
     build(l,mid,rt<<1);
     build(mid+1,r,rt<<1|1);
     pushup(l,r,rt);
}
void upnode(int p,int vv,int l,int r,int rt)
{
    if(l==r)
    {
        a[l]=vv;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) upnode(p,vv,l,mid,rt<<1);
    else if(p>mid) upnode(p,vv,mid+1,r,rt<<1|1);
    pushup(l,r,rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) return mx[rt];
    int mid=(l+r)>>1;
    int maxi=0;
    if(L<=mid&&mid<R)
    {
        maxi=max(query(L,R,l,mid,rt<<1),query(L,R,mid+1,r,rt<<1|1));
        if(a[mid]<a[mid+1])
        {
            int lll=min(mid-L+1,rr[rt<<1]);
            int rrr=min(R-mid,ll[rt<<1|1]);
            maxi=max(maxi,lll+rrr);
        }
    }
    else if(L<=mid) maxi=query(L,R,l,mid,rt<<1);
    else if(R>mid) maxi=query(L,R,mid+1,r,rt<<1|1);
    return maxi;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        getchar();
        getchar();
        char cc;
        int x,y;
         for(int i=1;i<=m;i++)
         {
             scanf("%c",&cc);
             scanf("%d%d",&x,&y);
             getchar();
             if(cc=='U')
             {
                 upnode(x,y,0,n-1,1);
             }
             else
             {
                  int hh=query(x,y,0,n-1,1);
                  printf("%d\n",hh);
             }
         }

    }
    return 0;
}

子序列,这里是直接将输入存一个数组,在数组里修改,而不是在树里修改,方便查询两个区间是否能构成连续上升序列

猜你喜欢

转载自www.cnblogs.com/Wangwanxiang/p/9418970.html