码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-04-04 12:42:56      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:序列   submit   script   五个   enter   scanf   node   struct   math   

[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: 我也不知道题目名字是什么

标签:序列   submit   script   五个   enter   scanf   node   struct   math   

原文地址:https://www.cnblogs.com/MT-LI/p/8714852.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!