BZOJ3521: [Poi2014]Salad Bar
2016-05-11 19:08
441 查看
题目大意:有一个长度为n的字符串,每一位只会是p或j。求一个最长子串,使得不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数。
首先先扫一遍得到以每个点为左端点,只考虑从左向右取,最远能取到哪,并标记每一个点最早被哪一个点扫到
然后再从后往前扫一遍,开两个栈,一个记录当前仍符合条件的右端点,一个记录已经被扫过的左端点,每当有元素从第一个栈里弹出时,就在第二个栈里二分找出符合两个条件的最远的左端点
#include<iostream>
#include<cstdio>
#define N 1000010
using namespace std;
char c
;
int pre
;
int s
,t;
int fir
,far
;
int b
,p;
int main()
{
int n;
scanf("%d",&n);
int i,j;
scanf("%s",c+1);
for(i=1;i<=n;i++)
{
if(c[i]=='p')
pre[i]=pre[i-1]+1;
else pre[i]=pre[i-1]-1;
}
for(i=1;i<=n;i++)
{
while(t&&pre[i]-pre[s[t]-1]<0)
{
far[s[t]]=i-1;
t--;
}
if(t) fir[i]=s[1];
else if(pre[i]-pre[i-1]==1) fir[i]=i;
else fir[i]=707185547;
if(pre[i]-pre[i-1]==1) t++,s[t]=i;
}
while(t)
{
far[s[t]]=n;
t--;
}
int ans=0;
int L,R,mid;
for(i=n;i>=1;i--)
{
while(t&&pre[s[t]]-pre[i-1]<0)
{
L=2;R=p+1;
while(L<R)
{
mid=(L+R)>>1;
if(far[b[mid]]>=s[t]) L=mid+1;
else R=mid;
}
ans=max(ans,s[t]-max(fir[s[t]]-1,b[L-1]-1));
t--;
}
if(pre[i]-pre[i-1]==1)
{
t++;s[t]=i;
while(p&&far[b[p]]<=far[i]) p--;
p++;b[p]=i;
}
}
while(t)
{
L=2;R=p+1;
while(L<R)
{
mid=(L+R)>>1;
if(far[b[mid]]>=s[t]) L=mid+1;
else R=mid;
}
ans=max(ans,s[t]-max(fir[s[t]]-1,b[L-1]-1));
t--;
}
printf("%d",ans);
}
首先先扫一遍得到以每个点为左端点,只考虑从左向右取,最远能取到哪,并标记每一个点最早被哪一个点扫到
然后再从后往前扫一遍,开两个栈,一个记录当前仍符合条件的右端点,一个记录已经被扫过的左端点,每当有元素从第一个栈里弹出时,就在第二个栈里二分找出符合两个条件的最远的左端点
#include<iostream>
#include<cstdio>
#define N 1000010
using namespace std;
char c
;
int pre
;
int s
,t;
int fir
,far
;
int b
,p;
int main()
{
int n;
scanf("%d",&n);
int i,j;
scanf("%s",c+1);
for(i=1;i<=n;i++)
{
if(c[i]=='p')
pre[i]=pre[i-1]+1;
else pre[i]=pre[i-1]-1;
}
for(i=1;i<=n;i++)
{
while(t&&pre[i]-pre[s[t]-1]<0)
{
far[s[t]]=i-1;
t--;
}
if(t) fir[i]=s[1];
else if(pre[i]-pre[i-1]==1) fir[i]=i;
else fir[i]=707185547;
if(pre[i]-pre[i-1]==1) t++,s[t]=i;
}
while(t)
{
far[s[t]]=n;
t--;
}
int ans=0;
int L,R,mid;
for(i=n;i>=1;i--)
{
while(t&&pre[s[t]]-pre[i-1]<0)
{
L=2;R=p+1;
while(L<R)
{
mid=(L+R)>>1;
if(far[b[mid]]>=s[t]) L=mid+1;
else R=mid;
}
ans=max(ans,s[t]-max(fir[s[t]]-1,b[L-1]-1));
t--;
}
if(pre[i]-pre[i-1]==1)
{
t++;s[t]=i;
while(p&&far[b[p]]<=far[i]) p--;
p++;b[p]=i;
}
}
while(t)
{
L=2;R=p+1;
while(L<R)
{
mid=(L+R)>>1;
if(far[b[mid]]>=s[t]) L=mid+1;
else R=mid;
}
ans=max(ans,s[t]-max(fir[s[t]]-1,b[L-1]-1));
t--;
}
printf("%d",ans);
}
相关文章推荐
- 三步解决网络稳定加载图片:使用到谷歌开源的Volley
- Android 常见bug汇总
- 闭包回调的写法
- 手写控件布局
- nyoj 115 dijkstra
- RabbitMQ 学习资料
- saltstack之(八)配置管理部署LAMP
- Linux下TC使用说明
- 【Android】17、体验活动的生命周期(下)
- Android startservice和bindservice
- ES5 数组方法every和some
- poj1083 贪心
- 关于finalize()方法(总结)
- 【连载】关系型数据库是如何工作的?(12) - 查询管理器之Statistics
- thinkphp模板页判断变量为空的方法
- 异步post请求之Block方法
- 【Android 基础】如何查看数字签名信息
- 关于ViewPager的点击事件的处理
- 关于jsp的一些问题和解答
- Android平台的 Ptrace, 注入, Hook 全攻略