01串 51Nod - 1391

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;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82926725