传送门

我是来帮加藤大佬写题解的……全世界都没找到加藤大佬写法的说明……很难受……

首先我们把\(p\)看成\(1\),\(j\)看成\(-1\),一个区间满足条件就意味着这个区间的所有前缀和都大于等于\(0\),所有后缀和都大于等于\(0\)

我们记录一下前缀和,所有前缀和大于等于\(0\)就是\(sum[i]-sum[l-1]\geq 0\),所有后缀和都大于等于\(0\)就意味着\(sum[n]-sum[i-1]\geq sum[n]-sum[r]\),即\(sum[i-1]\leq sum[r]\),然后因为\(sum[r]\geq sum[l-1]\)已经在第一个条件里满足了,所以合起来就是\(sum[i]\geq sum[l-1]\),\(sum[r]\geq sum[i]\)。用人话说,一个区间满足条件,那么这个区间内的\(sum\)都不小于\(sum[l-1]\)且\(sum[r]\)是这个区间中最大的数

于是我们定义\(to[i]\),意思是\([i,to[i]]\)中的所有数都大于等于\(sum[i]\),且\(sum[to[i]]\)为这个区间中最大的数,\(to[i]\)为所有满足条件的数中最靠右的。那么我们就可以枚举左端点\(i\),如果\(s[i]==j\)这个左端点肯定不行,否则这个左端点能匹配的最大的右端点就是\(to[i-1]\)

现在的问题就是怎么求出\(to[i]\)了,我们一开始先把所有的\(to[i]\)都赋值为\(i\),这样到时候可以少讨论一些边界情况。

首先,如果\(sum[i+1]<sum[i]\),即\(s[i+1]\)为\(p\),那么\(to[i]\)只能等于\(i\),因为它的下一个就小于它了。所以我们只考虑讨论\(s[i+1]\)为\(j\)的情况

我们考虑从后往前做,定义\(nxt[i]\)为它后面的第一个与它\(sum\)相等的位置,记录一个指针\(las\),表示每一次的\(to[i]\),现在做到了\(i\),那么\(las\)应该是指在\(to[i+1]\)的位置。

那么转移会有两种情况

1.\(to[i]=to[i+1]\),那么直接转移即可



2.\(to[i]\)变大。比如图中,\(k\)的位置才是\(to[i]\)



我们发现,在本题中,相邻两个数的值最多只会相差\(1\),于是若是存在如图\(2\)的情况,那么必然存在\(nxt[i]\)。不难证明\([i+1,nxt[i]-1]\)区间内的数肯定同时大于\(sum[i]\)或同时小于\(sum[i]\),如果全都小于那么有\(sum[i+1]<sum[i]\),我们之前已经处理掉了。所以\([i+1,nxt[i]-1]\)之间的数必然全都大于\(sum[i]\)。因为\(to[nxt[i]]\)已经求出来了,如果\(sum[to[nxt[i]]]\geq sum[las]\),我们可以把\([i,nxt[i]-1]\)这一段给接上去,那么新的区间\([i,to[nxt[i]]]\)肯定还是满足条件的,且不难证明不存在比它更优的。这种情况下我们让\(las\)指向\(to[nxt[i]]\)并更新\(to[i]\)即可。

只要处理出\([0,n-1]\)的所有的\(to[i]\)就可以了,最后的答案就是\(max\{to[i-1]-i+1\}(s[i]==p)\),时间复杂度\(O(n)\)

// luogu-judger-enable-o2
//minamoto
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,sum[N],head[N],nxt[N],to[N],mn;char s[N];
int main(){
// freopen("testdata.in","r",stdin);
memset(head,-1,sizeof(head));
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;++i)sum[i]=sum[i-1]+(s[i]=='p'?1:-1),mn=min(mn,sum[i]);
for(int i=n;~i;--i)
nxt[i]=head[sum[i]-mn],head[sum[i]-mn]=i,to[i]=i;
int ans=0;
for(int i=n,las=n;i;--i){
if(s[i]=='j')las=i-1;
else{
if(nxt[i-1]>=0&&sum[to[nxt[i-1]]]>=sum[las])las=to[nxt[i-1]];
to[i-1]=las,ans=max(ans,las-i+1);
}
}
printf("%d\n",ans);return 0;
}

P3564 [POI2014]BAR-Salad Bar的更多相关文章

  1. 【思维题 单调栈】loj#2430. 「POI2014」沙拉餐厅 Salad Bar

    t老师的做法好神…… 题目描述 桌面上有 n 个水果,分别是苹果和橘子.Bytea需要从水果中选择连续的一个区间,并从左到右或从右到左拿水果,且过程中橘子的数量必须始终不小于苹果的数量.求最长的区间大 ...

  2. 【BZOJ】3521: [Poi2014]Salad Bar

    题意 长度为\(n(1 \le n \le 1000000)\)的\(01\)字符串.找一个最长的连续子串\(S\),使得不管是从左往右还是从右往左取,都保证每时每刻已取出的\(1\)的个数不小于\( ...

  3. bzoj3521: [Poi2014]Salad Bar

    Description 有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个 ...

  4. 【LOJ】#2430. 「POI2014」沙拉餐厅 Salad Bar

    题解 波兰人的j是苹果,p是橘子 还真是跟中国过不去啊= =写的时候很难受 我们先求出每个点作为起点,能延伸到的最大长度,这个可以处理成前缀和,查询一下区间最小值是不是小于0,用st表实现,如果区间最 ...

  5. LOJ2430:[POI2014]沙拉餐厅Salad Bar——题解

    https://loj.ac/problem/2430 是的我BZOJ又没卡过……懒得卡了. 参考:https://blog.csdn.net/zqh_wz/article/details/52887 ...

  6. BZOJ3521 [Poi2014]Salad Bar 【线段树 + 单调栈】

    题目链接 BZOJ3521 题解 容易想到用前缀和搞 如果我们令\(p\)为\(1\),\(j\)为\(-1\),记前缀和为\(s[i]\) 我们就是要找到一段区间\([l,r]\),使得 \[\fo ...

  7. [POI2014]Salad Bar

    题目大意: 一个长度为$n(n\leq10^6)$的字符串,每一位只会是$p$或$j$.你需要取出一个子串$S$(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取 ...

  8. [Android]通知栏与操作栏的高度-State Bar & Navigation Bar

    1.通知栏 public static int getStatusBarHeight() { Resources resources = Resources.getSystem(); int reso ...

  9. 与Status Bar和Navigation Bar相关的一些东西

    Android Navigation Bar Status Bar   与StatusBar和NavigationBar相关的东西有两种,一是控制它们的显示与隐藏,二是控制它们的透明与否及背景. 在2 ...

随机推荐

  1. 【04】emmet系列之编辑器

     [01]emmet系列之基础介绍 [02]emmet系列之HTML语法 [03]emmet系列之CSS语法 [04]emmet系列之编辑器 [05]emmet系列之各种缩写 前端开发人员,常用的是s ...

  2. Qt5笔记之数据库(五)SQL表格模型QSqlTableModel

    教程网址:http://www.qter.org/portal.php?mod=view&aid=57 0.打开tablemodel.pro文件,加上: QT += coregui sql 注 ...

  3. 【转】Java中的IO操作

    在使用io操作之前,先看一下java中的文件类File如何使用.File包括文件和目录,对文件和目录的操作是新建目录mkdir,新建文件createNewFile,删除文件和目录delete,以及其他 ...

  4. hihoCoder#1051 补提交卡

    原题地址 简单贪心 首先,补提交卡应该连续使用,其次,补提交卡应该全部用掉(如果补提交卡多于未提交天数则额外处理) 所以,依次遍历未提交日期,计算:从当前位置开始,用M张补提交卡覆盖后面连续M个数字, ...

  5. jsp页面根据json数据动态生成table

    根据需求由于不同的表要在同一个jsp展示,点击某个表名便显示某张表内容,对于java后台传给jsp页面的json形式的数据是怎么动态生成table的呢? 找了好久,终于找到某位前辈的答案,在此表示衷心 ...

  6. 【BZOJ3925】地震后的幻想乡(期望概率DP,状压DP)

    题意:给定一张点数不超过10的无向连通图,每条边有一个[0,1]之间的随机权值,求最小生成树上最大边的期望值 提示:对于n个[0,1]之间的随机变量x1,x2,...,xn,第k小的那个的期望值是k/ ...

  7. Gym 100801 J. Journey to the “The World’s Start” DP+单调队列优化+二分

    http://codeforces.com/gym/100801 题目大意:有从左到右有n个车站,有n-1种车票,第i种车票一次最多可以坐 i 站(1<=i<=n)   每种票有固定的价钱 ...

  8. SOJ 3531_Number Pyramids

    [题意]给定一个数top及最底层元素个数n,构成一个以给top为塔尖,层数为n的如杨辉三角的金字塔,求有多少种 [分析]最终种数其实只与最底层的n个数的组合数有关,上层的每个都数是由最底层数相加得来 ...

  9. [bzoj2463][中山市选2009]谁能赢呢?_博弈论

    博弈论 bzoj-2463 中山市选-2009 题目大意:题目链接. 注释:略. 想法: 如果$n$是偶数的话就可以被多米诺骨牌恰好覆盖,这样的话只需要先手先走向(1,1)对应的第二段,后者必定会将棋 ...

  10. [bzoj2058][Usaco2010 Nov]Cow Photographs_树状数组_动态规划

    Cow Photographs bzoj-2058 Usaco-2010 Nov 题目大意:给定一个n的排列.每次操作可以交换相邻两个数.问将序列变成一个:$i,i+1,i+2,...,n,1,2,. ...