https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1391
一开始只想到线段树这种办法 真的智障
后来发现 化0为-1后 相邻前缀后缀只差1 所以对前缀只关心值大一的位置 对后缀只关心值小一的
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int det=1e6;
const int N=0x3f3f3f3f;
int ary[maxn],pre[maxn],suf[maxn];
int book[2*maxn],lef[maxn],rgt[maxn];
int n,len;
char ch[maxn];
int main()
{
int i,res,ans,p;
scanf("%s",ch);
n=strlen(ch);
for(i=0;i<n;i++)
{
if(ch[i]=='0') ary[i+1]=-1;
else ary[i+1]=1;
}
for(i=1;i<=n;i++) pre[i]=pre[i-1]+ary[i];
for(i=n;i>=1;i--) suf[i]=suf[i+1]+ary[i];
for(i=1;i<=n;i++) pre[i]+=det,suf[i]+=det;
memset(book,0x3f,sizeof(book));
book[det]=0;
for(i=1;i<=n;i++)
{
lef[i]=book[pre[i]+1];
if(book[pre[i]]==N) book[pre[i]]=i;
book[pre[i]]=min(book[pre[i]],book[pre[i]+1]);
}
memset(book,-1,sizeof(book));
book[det]=n+1;
for(i=n;i>=1;i--)
{
rgt[i]=book[suf[i]-1];
if(book[suf[i]]==-1) book[suf[i]]=i;
book[suf[i]]=max(book[suf[i]],book[suf[i]-1]);
}
ans=0;
for(i=1;i+1<=n;i++)
{
if(lef[i]!=N&&rgt[i+1]!=-1) ans=max(ans,rgt[i+1]-lef[i]-1);
}
printf("%d\n",ans);
return 0;
}
把0转为-1 问题就转为求最长的串 满足左负右正 对于每个前缀和pre[i] 看前面比它大的里面下标最小的 对于每个后缀和suf[i] 看后面比它小的里面下标最大的
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000010;
const int N=0x3f3f3f3f;
int minn[4*maxn];
int ary[maxn],pre[maxn],suf[maxn],tmp[maxn],lef[maxn],rgt[maxn];
int n,len;
char ch[maxn];
void update(int tar,int val,int l,int r,int cur)
{
int m;
minn[cur]=min(minn[cur],val);
if(l==r) return;
m=(l+r)/2;
if(tar<=m) update(tar,val,l,m,2*cur);
else update(tar,val,m+1,r,2*cur+1);
}
int query(int pl,int pr,int l,int r,int cur)
{
int res,m;
if(pl<=l&&r<=pr) return minn[cur];
res=N,m=(l+r)/2;
if(pl<=m) res=min(res,query(pl,pr,l,m,2*cur));
if(pr>m) res=min(res,query(pl,pr,m+1,r,2*cur+1));
return res;
}
int main()
{
int i,res,ans,p;
scanf("%s",ch);
n=strlen(ch);
for(i=0;i<n;i++)
{
if(ch[i]=='0') ary[i+1]=-1;
else ary[i+1]=1;
}
for(i=1;i<=n;i++)
{
pre[i]=pre[i-1]+ary[i];
tmp[i]=pre[i];
}
tmp[n+1]=0;
sort(tmp+1,tmp+n+2);
len=unique(tmp+1,tmp+n+2)-tmp-1;
for(i=1;i<=n;i++) pre[i]=lower_bound(tmp+1,tmp+len+1,pre[i])-tmp;
memset(minn,0x3f,sizeof(minn));
memset(lef,-1,sizeof(lef));
p=lower_bound(tmp+1,tmp+len+1,0)-tmp;
update(p,0,1,len,1);
for(i=1;i<=n;i++)
{
update(pre[i],i,1,len,1);
if(pre[i]+1<=len) res=query(pre[i]+1,len,1,len,1);
else res=N;
if(res!=N) lef[i]=res;
}
for(i=n;i>=1;i--)
{
suf[i]=suf[i+1]+ary[i];
tmp[i]=suf[i];
}
tmp[n+1]=0;
sort(tmp+1,tmp+n+2);
len=unique(tmp+1,tmp+n+2)-tmp-1;
for(i=1;i<=n;i++) suf[i]=lower_bound(tmp+1,tmp+len+1,suf[i])-tmp;
memset(minn,0x3f,sizeof(minn));
memset(rgt,-1,sizeof(rgt));
p=lower_bound(tmp+1,tmp+len+1,0)-tmp;
update(p,-n-1,1,len,1);
for(i=n;i>=1;i--)
{
update(suf[i],-i,1,len,1);
if(suf[i]-1>=1) res=query(1,suf[i]-1,1,len,1);
else res=N;
if(res!=N) rgt[i]=-res;
}
//for(i=1;i<=n;i++) printf("%d %d\n",lef[i],rgt[i]);
ans=0;
for(i=1;i+1<=n;i++)
{
if(lef[i]!=-1&&rgt[i+1]!=-1) ans=max(ans,rgt[i+1]-lef[i]-1);
}
printf("%d\n",ans);
return 0;
}