loj 2430 沙拉餐厅 Salad Bar

桌面上有 nnn 个水果,分别是苹果和橘子。Bytea需要从水果中选择连续的一个区间,并从左到右或从右到左拿水果,且过程中橘子的数量必须始终不小于苹果的数量。求最长的区间大小。

输入格式

第一行一个整数 nnn1≤n≤1000001 \le n \le 1000001n100000),表示水果个数。 接下来一行共有 nnn 个字符a1,a2,...,an(ai∈{j,p})a_1, a_2, ..., a_n (a_i \in \{j,p\})a1,a2,...,an(ai{j,p}),分别表示苹果和橘子(波兰语)。

输出格式

输出一行共一个数字,表示最长的区间大小。

样例

样例输入

6
jpjppj

样例输出

4
数据范围与提示

对于 20%20\%20% 的数据,n≤1000n \le 1000n1000.
对于 50%50\%50% 的数据,n≤10000n \le 10000n10000.
对于所有数据,1≤n≤1000001 \le n \le 1000001n100000.

解 :我们要知道p代表的是橘子,而且他很坑的一点是从左到右和从右到左都要满足橘子数不小于苹果数

那么我们可以从左到右扫找到每一个可行的区间,再从右向左扫,而且我们得保证从右向左扫获得的区间左端就是从左到右的最左端

比如       p  p  p  j  j  j  p  p                                                                            p    p    p    j     j      j     p    p

         -1 1  2  3  2 1 0  1  2            从左到右唯一可行区间就是从 0 到 8         3     2    1   -1    0    1     2    1     -1

显然我们找到的应该是 ppp   因为jjpp不满足从左到右

#include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#include<queue>
#include<deque>
#include<math.h>
#define ll long long
const ll inf=1e10;
using namespace std;
int n;
char s[1100000];
int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%s",s);
        int o=-1,x,y,ma=0;
        for(int i=0;i<=n;i++)//从左扫到右
        {
            if(i==n)//如果到已经全部扫完 
            {
                if(o>=0) //比如是ppp这种情况,因为我们平常是找到o为-1的话就找到了一段,而ppp没有-1情况,额外判断
                {
                        int u=n-1;
                        int oo=0;
                        for(int j=n-1;j>=x;j--)//从右往左,要找的x为止
                        {
                            if(s[j]=='p')
                                oo++;
                            else
                            {
                             oo--;
                             if(oo<0) oo=0,u=j-1;//o小于0,说明上一段不满足要求
                            }
                        }
                        ma=max(ma,u-x+1);
//                        i=u;//不确定需不需要,反正没有也能过
                        o=-1;
                }
                continue;
            }
            if(s[i]=='p')
            {
                o++;
                if(o==0)
                {
                    o=1;
                    x=i;
                }
            }
            else
            {
                o--;
                if(o<0)
                {
                    if(o==-1)
                    {
                        int u=i-1;
                        int oo=0;
                        for(int j=i-1;j>=x;j--)
                        {
                            if(s[j]=='p')
                                oo++;
                            else
                            {
                             oo--;
                             if(oo<0) oo=0,u=j-1;
                            }
                        }
                        ma=max(ma,u-x+1);
//                        i=u;
                   }
                    else
                        o=-1;
                }
            }
        }
        printf("%d\n",ma);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值