zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校赛(第三场)B-求01串中的最长01数量相等的子串和子序列

    https://ac.nowcoder.com/acm/contest/883/B

    首先先把0所在的位置变-1,1所在位置变1,然后统计一个前缀和,用sum[i]表示。

    那么如果从起点开始的话只要满足条件的子串那么sum[i]的值就是0

    如果子串起点不为0,那么只要以前出现过sum[i]的值,这两个值之间的串就一定是合法的子串。

    例如:

    标号:1  2  3  4  5 

    数值:0  0  1  1  0

    sum:-1 -2 -1 0 -1

    i==4的时候sum[i]==0,所以1-5间合法,长度是4

    而sum[1]==sum[3]==sum[5]==-1,所以第一次出现-1的位置是1,而最后出现的位置是5,所以其中长度5-1=4也是一个合法的区间子串。

    子序列就很简单了,只要求0,1的个数取最小数量乘2

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long int ll;
    typedef unsigned long long int ull;
    const int inf = 0x3f3f3f3f;
    int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}};
    #define pi acos(-1)
    #define ls rt<<1
    #define rs rt<<1|1
    #define me0(s) memset(s,0,sizeof(s))
    #define me1(s) memset(s,1,sizeof(s))
    #define mef(s) memset(s,-1,sizeof(s))
    #define meinf(s) memset(s,inf,sizeof(s))
    const int N=100005;
    int sum[N],t[N];
    inline int read() {
        char c=getchar(); int x=0, f=1;
        while(c<'0'|c>'9') {if(c=='-') f=-1;c=getchar();}
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    ll exgcd(ll a,ll b){
        if(b==0) return a;
        exgcd(b,a%b);
    }
    ll q_pow(ll a,ll b,ll mod){
        ll anss=1;
        while(b){
            if(b&1) anss=anss*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return anss;
    }
    ll q_mul(ll a,ll b,ll mod){
        ll anss=0;
        while(b){
            if(b&1) anss=(anss+a)%mod;
            a=(a+a)%mod;
            b>>=1;
        }
        return anss;
    }
    int main(int argc, char * argv[]) 
    {
        std::ios::sync_with_stdio(false);
        int n,l2=0,y2=0,ans2,v[N];
        mef(v);
        char s[N];
        cin>>n;
        cin>>s+1;
        int len=strlen(s+1);
        for(int i=1;i<=len;i++){
            if(s[i]=='1'){
                t[i]=1;
                y2++;
            }
            else{
                t[i]=-1;
                l2++;
            }
        }
        sum[1]=t[1];
        map<int,int>m;
        m[sum[1]]=1;
        int maxn=0;
        for(int i=2;i<=len;i++){
            sum[i]=sum[i-1]+t[i];  //算出sum
            if(m[sum[i]]!=0) maxn=max(maxn,i-m[sum[i]]);//如果出现过以前的sum值,则当前的位置减第一次的位置
            else m[sum[i]]=i;//否则记录第一个出现的sum值的位置
            if(sum[i]==0) maxn=max(maxn,i);//为0表示前面所有的01相等
    //        cout<<sum[i]<<" "<<m[sum[i]]<<endl;
        }
        ans2=2*(l2>y2?y2:l2);
        cout<<maxn<<" "<<ans2<<endl;
        return 0;
    }
  • 相关阅读:
    字体下载大宝库:30款好看的免费英文字体
    jQuery Mapael – 呈现动态的矢量地图
    Qt:用 __thread 关键字让每个线程有自己的全局变量
    从C++到Qt(舍弃IDE或qmake、cmake等工具的束缚,尝试通过几个例子)
    C++11(及现代C++风格)和快速迭代式开发
    EventBus + Redis发布订阅模式
    并发、并行和高并发
    Span<T>和Memory<T>
    Lucene.Net做一个简单的搜索引擎-全文索引
    技术架构演变
  • 原文地址:https://www.cnblogs.com/wushengyang/p/11243709.html
Copyright © 2011-2022 走看看