zoukankan      html  css  js  c++  java
  • Codeforces Round #646 (Div. 2)

    A:http://codeforces.com/contest/1363/problem/A

    题意:

    n个数,能否从中找到x个数,使得sum为奇数

    解析:

    比赛时被自己弄吐了,懒得一个一个分析,索性直接暴力枚举

    这破代码。。。各位不要学我啊。。。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int maxn=1e3+10;
    int a[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n,x;
            cin>>n>>x;
            int j=0,o=0;
            for(int i=1;i<=n;i++)
            {
                int md;
                cin>>md;
                if(md%2)
                    j++;
                else
                    o++;
            }
            if(j==0)
            {
                cout<<"NO"<<endl;
            }
            else if(o==0)
            {
                if(x%2)
                    cout<<"YES"<<endl;
                else
                    cout<<"NO"<<endl;
            }
            else
            {
                if(x%2==0)
                {
                    int ok=0,jj=1,oo=0;
                    while(jj<=j)
                    {
                        if((x-jj)<=o&&jj%2!=0)
                        {
                            ok=1;break;
                        }
                        else
                        {
                            jj++;
                        }
                    }
                    if(ok)
                        cout<<"YES"<<endl;
                    else
                        cout<<"NO"<<endl;
                }
                else
                {
                    if(j>=x)
                        cout<<"YES"<<endl;
                    else
                    {
                        int jj=1;
                        int ok=0;
                        while(jj<=j)
                        {
                            if(jj%2!=0&&(x-jj)<=o)
                            {
                                ok=1;break;
                            }
                            jj++;
                        }
                        if(ok)
                            cout<<"YES"<<endl;
                        else
                            cout<<"NO"<<endl;
                    }
                }
            }
        }
    }

    正经解析:

    其实不合法只有这三种情况:

    1:奇数数为0

    2:偶数数为0,x为偶数

    3:x==n,sum%2==0

    x<n&&j>0&&o>0是一定可以的,一定可以凑出奇数和来

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e3+10;
    int a[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n,x;
            cin>>n>>x;
            int sum=0,j=0;
            for(int i=1;i<=n;i++)
            {
                int md;
                cin>>md;
                sum+=md;
                if(md%2)
                    j++;
            }
            int o=n-j;
            if((x==n&&sum%2==0)||(j==0)||(o==0&&x%2==0))
                cout<<"NO"<<endl;
            else
                cout<<"YES"<<endl;
        }
    }

    B:http://codeforces.com/contest/1363/problem/B

    题意:

    给出的串,要把它变成不含010,101的串来(非连续子串),操作是反转0/1,求最小操作数

    解析:

    只有四种情况合法:

    全0:000000....

    全1:11111111...

    先全1,后全0:111111....000000.....

    先全0,后全1:00000.....111111......

    数据很小,所以可以暴力枚举每一种情况:156ms

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int maxn=1e3+10;
    int a[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            string s;
            cin>>s;
            int len=s.length();
            if(len==1||len==2)
            {
                cout<<"0"<<endl;continue;
            }
            int cnt=0;
            for(int i=1;i<len;i++)
            {
                if(s[i]!=s[i-1])
                    cnt++;
            }
            int cnt1=0,cnt0=0;
            for(int i=0;i<len;i++)
            {
                if(s[i]=='1')
                    cnt1++;
                else
                    cnt0++;
            }
            if(cnt==1||cnt==0||cnt1==0||cnt0==0)
            {
                cout<<"0"<<endl;continue;
            }        
            int minn=min(cnt1,cnt0);//00110
            for(int i=0;i<len;i++)
            {
                int sum=0;
                for(int j=i;j>=0;j--)
                {
                    if(s[j]=='0')
                        sum++;
                }
                for(int j=i+1;j<len;j++)
                {
                    if(s[j]=='1')
                        sum++;
                }
            //    cout<<i<<sum<<endl;
                minn=min(minn,sum);
            }
            for(int i=0;i<len;i++)
            {
                int sum=0;
                for(int j=i;j>=0;j--)
                {
                    if(s[j]=='1')
                        sum++;
                }
                for(int j=i+1;j<len;j++)
                {
                    if(s[j]=='0')
                        sum++;
                }
            //    cout<<i<<sum<<endl;
                minn=min(minn,sum);
            }
            cout<<minn<<endl;
        }
    }

    赛后反思:

    假如数据很大,就需要优化,对于第3,4情况,反转数实际上是某个位置之前的0数目+之后的1数目/之前的1数目+之后的0数目

    所以这里可以用前缀和处理一下:46ms,可以说是快多了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e3+10;
    int s1[maxn],s0[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            string s;
            cin>>s;
            memset(s1,0,sizeof(s1));
            memset(s0,0,sizeof(s0));
            int len=s.length();
            if(len==1||len==2)
                cout<<"0"<<endl;
            else
            {
                if(s[0]=='0')
                    s0[0]++;
                else
                    s1[0]++;
                for(int i=1;i<len;i++)
                {
                    s0[i]=s0[i-1];
                    s1[i]=s1[i-1];
                    if(s[i]=='0')
                        s0[i]++;
                    else
                        s1[i]++;
                }    
                int minn=min(s1[len-1],s0[len-1]);
                for(int i=0;i<len;i++)
                {
                    minn=min(minn,s1[i]+s0[len-1]-s0[i]);
                    minn=min(minn,s0[i]+s1[len-1]-s1[i]);
                }
                cout<<minn<<endl;
            }
        }
    }

    C:http://codeforces.com/contest/1363/problem/C

    题意:

    n个结点,n-1条边,只能拿掉入度为0/1的点,谁先拿到x,谁赢。

    解析:

    当x入度为0/1的时候,直接先手胜

    由于两个人都很聪明,每一步都要按最优来处理,所以谁都不想让对方赢,谁都不愿意先去靠近x,所以要把x点留到最后,即x入度==1的时候,这个时候,就确定了胜负了。

    所以看一下,除了x之外的n-1个点的奇偶性,当然也可以看n-2的奇偶性,这个无所谓的。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1e3+10;
    int d[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n , x;
            memset(d,0,sizeof(d));
            cin>>n>>x;
            for(int i=1;i<n;i++)
            {
                int l,r;
                cin>>l>>r;
                d[l]++;
                d[r]++;
            }
            if(d[x]==0||d[x]==1)
                cout<<"Ayush"<<endl;
            else if((n-1)%2==0)
                cout<<"Ashish"<<endl;
            else
                cout<<"Ayush"<<endl;
        }
    }
  • 相关阅读:
    Live2D 看板娘
    Live2D 看板娘
    Live2D 看板娘
    Live2D 看板娘
    Live2D 看板娘
    Live2D 看板娘
    [并发编程]并发编程第一篇:利用并发编程,实现查找大量数据中的素数
    [转载]Java数组扩容算法及Java对它的应用
    MineCraft note
    Hibernate一对一、一对多、多对多注解映射配置
  • 原文地址:https://www.cnblogs.com/liyexin/p/13026148.html
Copyright © 2011-2022 走看看