首页 > 代码库 > 线段树 HDU 3308

线段树 HDU 3308

题目大意:给你n个数,m个操作。操作有两种:1.U x y 将数组第x位变为y   2. Q x y 问数组第x位到第y位连续最长子序列的长度。对于每次询问,输出一个答案

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN   100010

struct node
{
    int l,r,ls,rs,ms;//维护从左边开始  最大   到右边结束 3个最长上升子序列个数
}x[MAXN<<3];

int z[MAXN],a1,b1;
void push_up(int a)
{
    int l=x[a].l,r=x[a].r;
    int mid=(l+r)>>1;
    x[a].ls=x[a<<1].ls;
    x[a].rs=x[a<<1|1].rs;
    x[a].ms=max(x[a<<1].ms,x[a<<1|1].ms);//这三条是显然的
    if(z[mid]<z[mid+1])//成立的话就要合并
    {
        if(x[a].ls==mid-l+1)//左边满 右孩子也左边要加上去
            x[a].ls+=x[a<<1|1].ls;
        if(x[a].rs==r-mid)  //同理
            x[a].rs+=x[a<<1].rs;
        x[a].ms=max(x[a].ms,x[a<<1].rs+x[a<<1|1].ls);//中间那段
    }
}

void Build(int l,int r,int a)
{
    x[a].l=l;
    x[a].r=r;
    if(l==r)
    {
        x[a].ls=x[a].rs=x[a].ms=1;
        return ;
    }
    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
    push_up(a);
}
void add(int l,int r,int a1,int a)//其实就是更新操作
{
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    if(a1<=mid)
        add(l,mid,a1,a<<1);
    else
        add(mid+1,r,a1,a<<1|1);
    push_up(a);
}

int Ques(int l,int r,int a1,int b1,int a)
{
    if(a1<=l&&r<=b1)
        return x[a].ms;
    int mid=(l+r)>>1;
    if(b1<=mid)
        return Ques(l,mid,a1,b1,a<<1);
    if(a1>mid)
        return Ques(mid+1,r,a1,b1,a<<1|1);
    int t1=Ques(l,mid,a1,b1,a<<1);
    int t2=Ques(mid+1,r,a1,b1,a<<1|1);
    int ans=max(t1,t2);//上面应该都能看懂
    if(z[mid]<z[mid+1])//这边合并可能成为答案
        ans=max(ans,min(b1-mid,x[a<<1|1].ls)+min(x[a<<1].rs,mid-a1+1));//如果x[a<<1|1].ls+mid>b1 那么查询范围就变大的了 所哟要取下min 左边同理
    return ans;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&z[i]);
        Build(1,n,1);
        while(m--)
        {
            char s[10];
            int a,b;
            scanf("%s%d%d",s,&a,&b);//变成从1开始
            a++;
            if(s[0]==U)
            {
                z[a]=b;
                add(1,n,a,1);//其实就是一个更新操作
            }
            else
            {
                b++;
                printf("%d\n",Ques(1,n,a,b,1));//查询
            }
        }
    }
    return 0;
}

 

线段树 HDU 3308