51nod 1931 思维 好题

链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1391

思路: https://blog.csdn.net/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

*/

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/82940340
今日推荐