POI2014 Salad Bar
Salad Bar
POI2014
题意
1.有一个长度为n的字符串,每一位只会是p或j。
2.找到一个子串S,使得不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数。
3.求S的最大长度。
解
1.把p看做+1,把j看做-1
2.设 sum[i]为前缀和
3.如果区间[l,r]要作为答案,必须满足一下条件
条件1:sum[l]~sum[r]-sum[l-1]>=0
(从左往右+1的个数总是不小于-1)
条件2:sum[r]-sum[r]~sum[l]>=0
(从右往左+1的个数总是不小于-1)
4.定义
ml[x]:x点向左第一个大于他的位置
mr[x]:x点向右第一个小于他的位置
单调栈预处理以上数组
5.枚举区间的左端点(左端点必须是p),二分查找最远的右端点
设枚举的左端点为l
根据条件1,右端点的可选区间为[l,mr[l-1]-1]
(因为sum[mr[l]]是第一个小于sum[l-1]的数)二分查找右端点时,
只要[mid,mr[l-1]-1]区间中存在一个mr[t]<l,就表示mid可行
(区间查询可以用ST表O(1)查询)
具体代码
#include<bits/stdc++.h>
using namespace std;
const int M=1000005;
char S[M];
int n,ans,sum[M],ml[M],mr[M];
int mi[M][20],Log[M];
void init(){Log[1]=0;for(int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;for(int i=1;i<=n;i++){mi[i][0]=ml[i];}for(int j=1;j<20;j++){for(int i=1;i+(1<<j)-1<=n;i++){mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);}}
}
int query(int L,int R){int k=Log[R-L+1];return min(mi[L][k],mi[R-(1<<k)+1][k]);
}
bool check(int L,int R,int mid){return query(mid,R)<L;
}
int main() {scanf("%d %s",&n,S+1);for(int i=1;i<=n;i++){sum[i]=sum[i-1];if(S[i]=='p')sum[i]++;else sum[i]--;}for(int i=n;i>=0;i--){int x=i+1;while(x<=n&&sum[x]>=sum[i])x=mr[x];mr[i]=x;}for(int i=1;i<=n;i++){int x=i-1;while(x>=1&&sum[x]<=sum[i])x=ml[x];ml[i]=x;}init();for(int i=1;i<=n;i++){if(S[i]=='j')continue;int L=i,R=mr[i-1]-1;while(L<=R){int mid=L+R>>1;if(check(i,mr[i-1]-1,mid)){L=mid+1;if(mid-i+1>ans){ans=mid-i+1;}}else{R=mid-1;}}}printf("%d\n",ans);return 0;
}
POI2014 Salad Bar相关推荐
- [POI2014]Salad Bar
题目大意: 一个长度为$n(n\leq10^6)$的字符串,每一位只会是$p$或$j$.你需要取出一个子串$S$(从左到右或从右到左一个一个取出),使得不管是从左往右还是从右往左取,都保证每时每刻已取 ...
- BZOJ3521: [Poi2014]Salad Bar
维护p-j的前缀和sum[i],那么一段l~r合法的充要条件是sum[l]<=sum[l~r],sum[r]>=sum[l~r],即中间的所有sum都>=sum[l],<=su ...
- bzoj 3521: [Poi2014]Salad Bar
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3521 POI的题果然都有一些很精妙的O(n)O(n)O(n)做法 带log的比较简单,这里就 ...
- P3564 [POI2014]BAR-Salad Bar(ST表 + 二分)
P3564 [POI2014]BAR-Salad Bar 给定一个长度为nnn的数组,里面元素只有111跟−1-1−1,问选出一个长度为lenlenlen的区间使得,这个区间的前缀和时刻大于零,后缀和 ...
- 【思维题 单调栈】loj#2430. 「POI2014」沙拉餐厅 Salad Bar
t老师的做法好神-- 题目描述 桌面上有 n 个水果,分别是苹果和橘子.Bytea需要从水果中选择连续的一个区间,并从左到右或从右到左拿水果,且过程中橘子的数量必须始终不小于苹果的数量.求最长的区间大 ...
- 【LOJ】#2430. 「POI2014」沙拉餐厅 Salad Bar
题解 波兰人的j是苹果,p是橘子 还真是跟中国过不去啊= =写的时候很难受 我们先求出每个点作为起点,能延伸到的最大长度,这个可以处理成前缀和,查询一下区间最小值是不是小于0,用st表实现,如果区间最 ...
- POI2014Salad Bar
POI2014 Salad Bar 这道题的大意就是给你一个字符串,里面只含有p和j,求一个最长的子串,使得从左边开始,p的个数一直比j多,从右边开始也一样. 这道题的话,一开始想歪了,就先对每个字符 ...
- POI 2014 切题记
POI 2014 Salad Bar Description: 有一个长度为nnn的字符串,每一位只会是ppp或jjj.你需要取出一个子串SSS(从左到右或从右到左一个一个取出),使得不管是从左往右还 ...
- 8000 sentences of oral English(four)
第四章 表现感情的短句 (16)高兴时 ●欣喜 How's your newhome? --I'm happy. 我很高兴!我很幸福! I'm ecstatic. 狂喜 I'm thrilled. 我 ...
最新文章
- mysql 挂掉 无法启动_mysql-配置 - MySQL错误,时不时自动挂掉,无法启动
- 怎么配置搭建Nginx网站服务器
- Django View使用装饰器捕获数据库连接异常
- 算法心经:数学的应用:概率的应用
- 【-】WebKit Layout (布局)
- jms、amqp、mqtt区别与联系
- linux下ssh通过公钥登录服务器
- C语言 显示器键盘io
- lucene全文检索mysql教程_对于数据库里的多张表怎么利用lucene等实现全文检索
- springboot security 安全
- Android酷炫有用的开源框架
- 如何成为更高级别的iOS开发工程师?
- 物联网云平台系统设计
- 关于数字证书链的一点认知
- 六十六条经典禅语名句
- 揭密巴西Banrisul银行网站遭遇5小时劫持的原因
- Unity流水账14:GL、Graphics及CommandBuffer
- C语言实现实数和复数矩阵及其各种运算(一)
- Django连接MySQL对数据进行网页展示
- 数字IC设计随笔之七(TCL脚本编程入门)
热门文章
- 7-6 厘米换算英尺英寸
- 全球与中国心里健康平台市场现状及未来发展趋势2022-2028
- web前端之CSS3
- 开源真的在蚕食整个世界吗
- java毕业设计大学生二手物品交易网站演示记录2021Mybatis+系统+数据库+调试部署
- coda2怎么连接mysql_Coda 2.7.7 - Web管理通用工具包
- 服务搭建篇(七) Elasticsearch单节点部署以及多节点集群部署
- C++注释的几种方法
- 黑马毕向东Java课程笔记(day20-1——20-17)IO流:File类及相关方法、递归、递归的相关练习、Properties、PrintWriter类与PrintStream类、合并流与切割流
- 82.Hive SQL插入动态分区的异常分析