BZOJ4491: 我也不知道题目名字是什么

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4491: 我也不知道题目名字是什么相关的知识,希望对你有一定的参考价值。

[Submit][Status][Discuss]

Description

给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串

Input

第一行n,表示A数组有多少元素
接下来一行为n个整数A[i]
接下来一个整数Q,表示询问数量
接下来Q行,每行2个整数l,r
N,Q<=50000

 

Output

对于每个询问,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串

Sample Input

9
1 2 3 4 5 6 5 4 3
5
1 6
1 7
2 7
1 9
5 9

Sample Output

6
6
5
6
4
//样例解释
五个询问分别对应
[1,6][1,6][2,6][1,6][6,9]
 
 
停课之后有点萎靡。。。
一眼线段树,据说这是个经典问题??
我觉得我的码力还可以啊
有一个小细节:记得要把0算两种情况
 
代码如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n,Q;
int a[510000];
struct trnode{
    int l,r,lc,rc,c;//c表示这个l~r中最长的不上升或不下降 
    int lm,rm;int la,ra;//lm从左开始的不上升,la从左开始的不下降 
}tr[2100000];int trlen;
void bt(int l,int r)
{
    int now=++trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=0;
    tr[now].lc=tr[now].rc=-1;
    tr[now].lm=tr[now].rm=tr[now].la=tr[now].ra=0;
    if(l==r)
    {
        if(a[l]<=0)tr[now].rm=tr[now].lm=1;
        if(a[l]>=0)tr[now].la=tr[now].ra=1;
        tr[now].c=1;
    }
    else if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
        int lc=tr[now].lc,rc=tr[now].rc;
        
        tr[now].lm=tr[lc].lm;
        if(tr[lc].lm==tr[lc].r-tr[lc].l+1)tr[now].lm+=tr[rc].lm;
        tr[now].la=tr[lc].la;
        if(tr[lc].la==tr[lc].r-tr[lc].l+1)tr[now].la+=tr[rc].la;
        tr[now].rm=tr[rc].rm;
        if(tr[rc].rm==tr[rc].r-tr[rc].l+1)tr[now].rm+=tr[lc].rm;
        tr[now].ra=tr[rc].ra;
        if(tr[rc].ra==tr[rc].r-tr[rc].l+1)tr[now].ra+=tr[lc].ra;
        
        int minx,maxx;
        minx=max( max(tr[now].lm,tr[lc].c),max(tr[now].rm,tr[lc].rm+tr[rc].lm) );
        maxx=max( max(tr[rc].c,tr[now].la),max(tr[now].ra,tr[lc].ra+tr[rc].la) );
        tr[now].c=max( minx , maxx  );    
    }
}
int findmax(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(mid+1<=l)return findmax(rc,l,r);
    else if(r<=mid)return findmax(lc,l,r);
    else
    {
        int lx=findmax(lc,l,mid),rx=findmax(rc,mid+1,r);
        int jiehe_max=min(tr[lc].r-l+1,tr[lc].ra)+min(r-tr[rc].l+1,tr[rc].la);
        int jiehe_min=min(tr[lc].r-l+1,tr[lc].rm)+min(r-tr[rc].l+1,tr[rc].lm);    
        return max(max(jiehe_max,jiehe_min),max(lx,rx));
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<n;i++)a[i]=a[i+1]-a[i];
    trlen=0;bt(1,n-1);
    scanf("%d",&Q);
    while(Q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        if(l==r){printf("1\n");continue;}
        if(l>r)swap(l,r);
        r--;
        printf("%d\n",findmax(1,l,r)+1);
    }
    return 0;
}

by_lmy

以上是关于BZOJ4491: 我也不知道题目名字是什么的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 4491: 我也不知道题目名字是什么 RMQ

bzoj4491 我也不知道题目名字是什么

BZOJ4491: 我也不知道题目名字是什么

bzoj4491 我也不知道题目名字是什么

BZOJ4491: 我也不知道题目名字是什么

BZOJ1034省队选手不务正业打泡泡堂(我也不知道是啥算法)