1391 01串
题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注
给定一个01串S,求出它的一个尽可能长的子串S[i..j],满足存在一个位置i<=x <j, S[i..x]中0比1多,而S[x + 1..j]中1比0多。求满足条件的最长子串长度。
Input
一行包含一个只由0和1构成的字符串S。 S的长度不超过1000000。
Output
一行包含一个整数,表示满足要求的最长子串的长度。
Input示例
10
Output示例
0
曹鹏 (题目提供者)
比较脑残 只想到无脑rmq O(nlogn)
sum[i+1]=sum[i]+(str[i]=='1'?1:-1);
求出串的前缀和
问题就转换为 存在一个x 使得((sum[i]==sum[x]&&sum[x]-sum[x-1])<0)||sum[i]>sum[x])&&sum[x]<sum[j]
rmq查询[1,x-1]中大于sum[x]的最小下标
[x+1,n]中大于sum[x]的最大下标
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<vector>
#include<deque>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include <string.h>
#include<math.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int inf=1e9+7;
const int N = 1000000+5;
char str[N];
int sum[N];
int rmq[4*N];
void add(int k,int l,int r,int pos,int var){
if(l<=pos&&pos<=r){
rmq[k]=max(rmq[k],var);
if(l!=r){
int mid=(l+r)/2;
if(pos<=mid){
add(2*k+1,l,mid,pos,var);
}
if(pos>=mid+1){
add(2*k+2,mid+1,r,pos,var);
}
}
}
}
int queryL(int k,int l,int r,int pos,int var){
if(l<=pos){
if(l==r){
return l;
}
int mid=(l+r)/2;
if(rmq[2*k+1]>var){
return queryL(2*k+1,l,mid,pos,var);
}
return queryL(2*k+2,mid+1,r,pos,var);
}
return inf;
}
int queryR(int k,int l,int r,int pos,int var){
if(r>pos){
if(l==r){
return r;
}
int mid=(l+r)/2;
if(rmq[2*k+2]>var){
return queryR(2*k+2,mid+1,r,pos,var);
}
return queryR(2*k+1,l,mid,pos,var);
}
return -inf;
}
int main()
{
//freopen("/home/lu/Documents/r.txt","r",stdin);
while(~scanf("%s",str)){
fill(rmq,rmq+4*N,-inf);
sum[0]=0;
int n=strlen(str);
add(0,0,n,0,sum[0]);
for(int i=0;i<n;++i){
sum[i+1]=sum[i]+(str[i]=='1'?1:-1);
add(0,0,n,i+1,sum[i+1]);
}
int ans=0;
for(int i=1;i<=n;++i){
int l=str[i-1]=='0'?i:inf;
l=min(l,queryL(0,0,n,i,sum[i])+1);
int r=queryR(0,0,n,i,sum[i]);
ans=max(ans,r-l+1);
}
printf("%d\n",ans);
}
return 0;
}