Jump

话说世界上有很多超级英雄:蝙蝠侠,蜘蛛侠,超人,名字都写不出来的人等等。在他们之中有一个叫Kickass。今天他想模仿蜘蛛侠,所以他选择了一排高楼来跳。

具体来说,他选择了一列N幢高楼,从左到右标号为1到N。一开始他在第K幢高楼。不幸的是,Kickass能力非常有限,只能跳到向左或向右相邻的高楼,而且他要跳到的楼的高度必须不能大于他现在处在的楼的高度。Kickass不想自己看起来很渣渣,所以他在一些高楼顶部放了蹦床,从这些高楼起跳,能跳到任何其他的高楼,不管要跳到的高楼在哪里或是多高。

你的任务是找到Kickass在第K高楼起跳能跳到的最多不同的高楼数。如果Kickass跳到一幢高楼超过一次,我们只会算一次。并且,即使Kickass没有重新跳到,第K幢高楼还是要算入答案。

Input

第一行输入两个数:高楼数 N(3<=N<=300,000),起跳位置K(1<=K<=N)。

第二行包括N个小于10^6的整数,表示1到N高楼的高度。

第三行包括一行N个字符’.’或’T’。如果第i个字符为’T’,则第i幢楼上有蹦床。

Output

输出一行,最多可以跳到的高楼数。

这种题要学会把握问题实质。
可以看出每个弹簧都有一个范围,只要你能到达某个弹簧那么所有弹簧范围都能达到,然后最后一步走个最长连续单调序列就好。如果不能到达任意弹簧(没被弹簧范围覆盖)就从该位置开始走个最长单调序列。
小心相等情况,如果相等,比如说你从起点向左序列相等,向右单调长,那么你可以先向左走再向右走。

总之,解题关键是有没有看出弹簧范围。

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std ;

#define N 300010

int i , j , k , n , st , T ;

int a[N] , cov[N] ;

bool range[N] ;

char s[N] ;

struct Jumper {
    int r , l ;
}z[N] ;

int main() { 
    scanf("%d%d",&n,&st ) ;
    for( i=1 ; i<=n ; i++ ) scanf("%d",&a[i] ) ;
    scanf("%s",s ) ;
    for( i=1 ; i<=n ; i++ )  {
        if( s[i-1]=='T' && cov[i]==0 ) {
            range[i] = 1 ; 
            for( j=i-1 ; j>0 ; j-- ) {
                if( a[j]<a[j+1] ) break ;
                range[j] = 1 ;
                if( s[j-1]=='T' ) {
                    z[i].l = z[j].l ;
                    cov[i] = 1 ;
                    break ;
                }
            }
            if( !z[i].l ) z[i].l = j+1 ;
            for( j=i+1 ; j<=n ; j++ ) {
                if( a[j]<a[j-1] ) break ;
                range[j] = 1 ;
                if( s[j-1]=='T' ) cov[i] = 1 ;

            }
            z[i].r = j-1 ;
        }
    }
    int ans = 0 ;
    if( range[ st ] ) {
        int cnt = 0 ;
        range[0] = range[ n+1 ] = 1 ;
        for( i=1 ; i<=n ; i++ ) {
            if( range[i-1] || a[i]<=a[i-1] ) cnt ++ ; else cnt = 1 ;
            if( range[i] ) cnt = 0 ;
            ans = max( ans , cnt ) ;
        }
        cnt = 0 ;
        for( i=n ; i ; i-- ) {
            if( range[i+1] || a[i]<=a[i+1] ) cnt ++ ; else cnt = 1 ;
            if( range[i] ) cnt = 0 ;
            ans = max( ans , cnt ) ;
        }
        for( i=1 ; i<=n ; i++ ) ans += range[i] ;
    } else {
        for( i=st+1 ; i<=n ; i++ ) if( a[i]>a[i-1] ) break ;
        int r = i  ;
        for( i=st-1 ; i ; i-- ) if( a[i]!=a[i+1] ) break ;
        int _r = i+1 ;
        for( i=st-1 ; i> 0 ; i-- ) if( a[i]>a[i+1] ) break ;
        int l = i  ; 
        for( i=st+1 ; i<=n ; i++ ) if( a[i]!=a[i-1] ) break ;
        int _l = i-1 ;
        ans =  max( r - _r , _l - l ) ;
    }
    printf("%d\n",ans ) ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值