链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1391
思路: https://blog.youkuaiyun.com/caduca/article/details/48007559
当然如果这里将字符串中的0 看成-1 那么如果我枚举中间点x ,那么他的前边所能到达的地方肯定是第一个出现的cur+1的位置,那么我也可以在线段树上二分查找。后边所能到达的地方同理。
o(n) 代码(用了map 不是严格意义上o(n),但是稍微加个小技巧就可以去掉map 所以思想是n的 ):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =2e6+5;
int pre[N];
int post[N];
map<int ,int >fir1;
map<int ,int >fir2;
char s[1000005];
int n;
int main()
{
scanf("%s",s+1);
memset(pre,-1,sizeof(pre));
memset(post,-1,sizeof(post));
n=strlen(s+1);
int cur=0;
for(int i=1;i<=n;i++){
if(s[i]=='0') cur--;
else cur++;
if(cur<0) pre[i]=0;
else{
if(fir1[cur+1]==0){
pre[i]=-1;
}
else pre[i]=fir1[cur+1];
}
if(fir1[cur]==0){
fir1[cur]=i;
}
}
cur=0;
for(int i=n;i>=1;i--)
{
if(s[i]=='0') cur--;
else cur++;
if(cur>0) post[i]=n+1;
else{
if(fir2[cur-1]==0){
post[i]=-1;
}
else post[i]=fir2[cur-1];
}
if(fir2[cur]==0){
fir2[cur]=i;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(pre[i]==-1||post[i]==-1) continue;
ans=max(ans,post[i]-pre[i]-1);
}
printf("%d\n",ans);
return 0;
}
/*
01010110
101001010110
*/
nlongn 线段树二分
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
const int N =1e6+5;
int pre[N];
int post[N];
char s[N];
int n;
struct node
{
int l,r;
int mx,mn;
}tr[N<<2];
int in1[N];
int in2[N];
void push_up(int i)
{
tr[i].mn=min(tr[lson].mn,tr[rson].mn);
tr[i].mx=max(tr[lson].mx,tr[rson].mx);
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r;
if(l==r){
tr[i].mx=pre[l];
tr[i].mn=post[l];
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
}
int query1(int i,int L,int R,int aim)
{
int l=tr[i].l,r=tr[i].r;
if(L<=l&&r<=R)
{
if(tr[i].mx>=aim)
{
if(l==r) return l;
else{
int mid=(L+R)>>1;
int ls=0,rs=0;
ls=query1(lson,L,R,aim);
if(ls) return ls;
rs=query1(rson,L,R,aim);
return rs;
}
}
else return 0;
}
int mid=(l+r)>>1;
int ls=0,rs=0;
if(L<=mid) ls=query1(lson,L,R,aim);
if(ls) return ls;
if(R>mid) rs=query1(rson,L,R,aim);
return rs;
}
int query2(int i,int L,int R,int aim)
{
int l=tr[i].l,r=tr[i].r;
if(L<=l&&r<=R)
{
if(tr[i].mn<=aim)
{
if(l==r) return r;
else{
int mid=(l+r)>>1;
int ls=0,rs=0;
rs=query2(rson,L,R,aim);
if(rs) return rs;
ls=query2(lson,L,R,aim);
return ls;
}
}
else return 0;
}
int mid=(l+r)>>1;
int ls=0,rs=0;
if(R>mid) rs=query2(rson,L,R,aim);
if(rs) return rs;
if(L<=mid) ls=query2(lson,L,R,aim);
return ls;
}
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
for(int i=1;i<=n;i++){
if(s[i]=='0') pre[i]=pre[i-1]-1;
else pre[i]=pre[i-1]+1;
}
for(int i=n;i>=1;i--){
if(s[i]=='0') post[i]=post[i+1]-1;
else post[i]=post[i+1]+1;
}
build(1,1,n);
memset(in1,-1,sizeof(in1));
memset(in2,-1,sizeof(in2));
int cur;
for(int i=1;i<=n;i++)
{
cur=pre[i];
if(cur<0){
in1[i]=0;
continue;
}
//printf("cur: %d aim %d\n",cur,cur+1);
int in=query1(1,1,i,cur+1);
//printf("%d\n",in);
if(in==0) in1[i]=-1;
else{
in1[i]=in;
}
}
for(int i=n;i>=1;i--)
{
cur=post[i];
if(cur>0){
in2[i]=n+1;
continue;
}
int in=query2(1,i,n,cur-1);
if(in==0) in2[i]=-1;
else{
in2[i]=in;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(in1[i]==-1||in2[i]==-1) continue;
ans=max(ans,in2[i]-in1[i]-1);
}
printf("%d\n",ans);
return 0;
}
/*
01010110
*/